小编Mar*_*mke的帖子

SQL Server:表中的最大行数

我开发的软件在其数据库表(SQL Server版本8,9或10)中存储了大量数据.假设每天大约有100,000条记录插入到该表中.这大约是每年3600万条记录.由于担心我会失去性能,我决定每天创建一个新表(一个名称中包含当前日期的表)以降低每个表的记录数.

你能告诉我,这是不是一个好主意?SQL服务器表是否有记录限制?或者您知道在性能显着降低之前可以在表中存储多少条记录(或多或少)?

sql-server database-design

73
推荐指数
7
解决办法
17万
查看次数

是否有必要在Delphi中将字符串转换为WideString?

我找到了一个Windows API函数,它执行字符串的"自然比较".它的定义如下:

int StrCmpLogicalW(
    LPCWSTR psz1,
    LPCWSTR psz2
);
Run Code Online (Sandbox Code Playgroud)

要在Delphi中使用它,我这样说:

interface
  function StrCmpLogicalW(psz1, psz2: PWideChar): integer; stdcall;

implementation
  function StrCmpLogicalW; external 'shlwapi.dll' name 'StrCmpLogicalW';
Run Code Online (Sandbox Code Playgroud)

因为它比较了Unicode字符串,所以当我想比较ANSI字符串时,我不确定如何调用它.似乎足以将字符串转换为WideString然后转换为PWideChar,但是,我不知道这种方法是否正确:

function AnsiNaturalCompareText(const S1, S2: string): integer;
begin
  Result := StrCmpLogicalW(PWideChar(WideString(S1)), PWideChar(WideString(S2)));
end;
Run Code Online (Sandbox Code Playgroud)

我对字符编码知之甚少,所以这就是我提问的原因.这个函数是OK还是我应该首先以某种方式转换两个比较的字符串?

delphi string widestring

19
推荐指数
2
解决办法
2万
查看次数

以用户友好的方式对包含数字的字符串进行排序

习惯于对字符串进行排序的标准方法,当我注意到Windows以某种高级方式按名称对文件进行排序时,我感到很惊讶.让我给你举个例子:

Track1.mp3
Track2.mp3
Track10.mp3
Track20.mp3

我认为这些名称是根据字母和数字分别比较(在排序期间).

另一方面,以下是以标准方式排序的相同列表:
Track1.mp3
Track10.mp3
Track2.mp3
Track20.mp3

我想在Delphi中创建一个比较算法,让我以相同的方式对字符串进行排序.起初我认为比较两个字符串的连续字符就足够了.当在两个字符串的某个位置找到一个数字时,我会读取它们后面的所有数字以形成一个数字,然后比较这些数字.

举个例子,我将用这种方式比较"Track10"和"Track2"字符串:
1)读取字符时它们是相等的,而它们是字母:"Track","Track"
2)如果找到一个数字,读取以下所有数字:"10","2"
2a)如果它们相等,则转到1或者完成
Ten大于2,因此"Track10"大于"Track2"

似乎一切都会好的,直到我在测试期间发现Windows认为"Track010"低于"Track10",而我认为第一个更长,因为它更长(没有提到根据我的算法字符串将是相等的,这是错误的).

你能否告诉我Windows如何按名称对文件进行排序,或者你有一个我可以使用的即用型算法(使用任何编程语言)?

非常感谢!
马里乌什

sorting algorithm text numbers

18
推荐指数
1
解决办法
2万
查看次数

一种破坏TThread对象的正确方法

这个问题似乎微不足道,但我希望你不要忽视它.
在销毁TThread对象之前,通常需要等到调用TThread.Execute()方法的线程完成,因为只有这样我们才能确定,例如,不再访问在类的析构函数中销毁的对象.因此,有必要调用Terminate来设置线程必须检查的Terminated标志以知道是否退出,然后调用WaitFor()方法.

因为线程可能被挂起,我认为在调用WaitFor之前恢复它是好的,否则调用线程将会死锁.并且因为线程可以多次挂起,所以应该恢复相同的次数,对吗?

while Suspended do
  Resume;
Run Code Online (Sandbox Code Playgroud)

如果线程被创建为暂停,我们不必担心当我们恢复线程只会终止它时将调用TThread.Execute()方法 - 它不会(如果我错了请纠正我).

我所说的建议为每个被释放的TThread对象使用以下代码行:

MyThread.Terminate;
while MyThread.Suspended do
  MyThread.Resume;
MyThread.WaitFor;
MyThread.Free;
Run Code Online (Sandbox Code Playgroud)

不幸的是,当我们销毁创建多个线程的应用程序时,为每个被破坏的TThread对象编写这样一段代码会使代码变得非常长,甚至可能不透明.

因此我得出结论,所有这些都可以放在TThread类的重写析构函数中,这要归功于调用MyThread.Free(如果设置了MyThread.FreeOnTerminate,则调用MyThread.Terminate),而不关心是否销毁object是否是TThread对象:

destructor TMyThread.Destroy;
begin
  //if FreeOnTerminate, the calling thread cannot wait for itself
  if GetCurrentThreadId <> ThreadId then
  begin
    Terminate;
    while Suspended do
      Resume;
    WaitFor;
  end;

  {free all objects created in this class}

  inherited Destroy;
end;
Run Code Online (Sandbox Code Playgroud)

请原谅我提出这样一个基本问题.但是,我希望通过这种方式了解您的意见 - 我希望这是一种普遍的方式 - 销毁TThread对象.我问这个问题,因为我从我的同事的代码中学到了他们通常使用第一个代码示例来销毁这些对象,但他们从来没有用来检查等待的线程是否没有被挂起,如果线程我认为有点危险可能会在代码中的某处暂停.因此,我试图找到一种破坏这个类的对象的通用方法,这将使代码更清晰,更安全.我希望我没有让情况变得更糟 - 你怎么看?

提前感谢您的建议.

delphi destructor tthread

16
推荐指数
2
解决办法
1万
查看次数

为什么在调用Dispose之前必须转换为特定的指针类型?

假设我有一个TList类的实例(BDS 2006,所以这是一个指针类型列表).我放入列表的每个指针都引用New()函数分配的内存.因此,当我想清除列表时,我必须遍历它并处理每个项目,对吧?但如何正确地做到这一点?我是否必须将每个处理过的物品投射到它的实际类型?

type
  TMyRec = record
    Field1: string;
    Field2: integer;
  end;
  PMyRec = ^TMyRec;

  ...

  var
    MyList: TList;
    MyRecPointer: PMyRec;
  begin
    ...
    New(MyRecPointer);
    ...
    MyList.Add(MyRecPointer);
    ...

    for i := 0 to MyList.Count - 1 do
      Dispose(PMyRec(MyList[x]));        

    MyList.Clear();
  end;
Run Code Online (Sandbox Code Playgroud)

请查看最后的for循环.我将每个项目投射到PMyRec以处置内存.这有必要吗?我知道Dispose()函数有一个Pointer参数,所以在这种情况下,转换似乎很愚蠢,但我仍然不确定.因为Dispose()函数如何知道在获得一般指针类型时要处理多少内存?

这是第二种方法(没有类型转换):

for i := 0 to MyList.Count - 1 do
  Dispose(MyList[x]);  
Run Code Online (Sandbox Code Playgroud)

如果有人解释我该怎么做以及为什么,我将不胜感激.非常感谢.

delphi pointers dispose casting

12
推荐指数
1
解决办法
604
查看次数

如何将Delphi项目正确划分为BPL?

我工作的公司在Delphi中开发了一个系统,它包含许多exe模块,如果涉及源代码,它们在某种程度上是相同的.遗憾的是,没有人关心使用库来共享代码.这意味着每次在代码中都有错误修复所有这些模块共享时,程序员必须分别对所有这些模块进行修正!它总是需要这么多时间......

我决定找到一种方法将共享代码放入库中.我考虑过DLL和BPL.在这种情况下,BPL似乎更方便程序员,更不麻烦,特别是代码仅在我们的软件中使用,并且仅在Delphi中使用.

我将所有exe模块共享的所有代码放入BPL中,一切看起来都很好,但有些事我不明白,如果你向我解释,我将不胜感激.

  1. 在将代码划分为BPL之后我的期望是,使用我创建的BPL部署exe文件就足够了.但事实证明他们也需要一个rtl100.bpl和vcl100.bpl.为什么会这样?我想只部署exes和我的BPL.我不想为最终用户提供由Borland和第三方公司提供的一大堆库:).我希望它们在exes中编译,就像之前编译的那样.有可能吗?

  2. 到目前为止我做的是:

    • 我把所有共享的pas单位都放到BPL上.每个BPL包含属于同一类别的单元,因此程序员可以清楚地了解给定BPL中的代码.
    • 每个BPL都是"运行时和设计时"库.
    • 每个BPL都是"明确重建".后两者是BPL的默认项目设置.
  3. 如果涉及到exe项目:

    • 我删除了我之前提交给BPL的所有单位.
    • 我在BDS 2006的Tools-> Install package菜单中安装了我的BPL.
    • 在我的exe项目设置中,我选中了"使用运行时包构建"选项,并在下面的编辑框中列出了我的所有BPL包(仅限我的包,因为我清除了那里出现的所有其他包).

这就是我所做的一切.exe项目编译正确,但我无法访问BPL的源代码(我无法从我的exe项目导航到该代码),即使所有BPL与其源代码文件一起存储.为什么?这对我来说似乎很奇怪.

我总是倾向于写冗长的描述 - 抱歉:).我将感谢你的帮助.我只需要对我提到的要点进行一些解释:仅使用我的BPL部署exe,我作为一个整体做的正确性,以及无法导航到BPL源代码.非常感谢你提前!


谢谢大家的讨论.有人说我选择的方法并不是一个好主意.我们的软件包含100多个模块(大多数模块类似于不同设备的驱动程序).他们中的大多数共享相同的代码 - 在大多数情况下是类.问题是这些类并不总是放在单独的独立的pas单元中.我的意思是共享代码通常放在包含特定于模块的代码的单元中.这意味着当您修复共享类中的错误时,仅将定义的pas单元复制到所有软件模块并重新编译它们是不够的.不幸的是,您必须将固定的代码片段逐个复制并粘贴到每个模块中,并将其粘贴到适当的单元和类中.这需要花费很多时间,这是我想要消除的,选择正确的方法 - 请帮助我.

我认为使用BPL是一个很好的解决方案,但它有一些缺点,正如你们有些人提到的那样.最糟糕的问题是,如果每个EXE需要几个BPL,我们的技术支持人员将不得不知道哪个EXE需要哪个BPL,然后为最终用户提供适当的文件.只要我们没有软件更新程序,这对我们的技术人员和最终用户来说都是一个很大的优势.他们肯定会迷茫和愤怒: - /.

兼容性问题也可能发生 - 如果一个BPL由许多EXE共享,一个BPL的修改对于一个EXE是好的而对另一个也是坏的 - @Warren P.

那么我应该怎么做才能在这么多项目中更快地修复错误?我想到了以下方法之一.如果您有更好的想法,请告诉我.

  • 将共享代码放入单独的独立的pas单元中,因此当其中一个错误修复时,将其复制到所有项目(覆盖旧文件)并重新编译所有项目就足够了.

只要修改了后面修改的代码,这个解决方案似乎就可以了.但是我们也有具有一般使用功能和程序的通行单元,这通常是不可修改的 - 我们在必要时在那里添加新功能,但是在单个项目中.因此,假设您在100个模块中的一个模块中编写了一个新函数,并将其放入其通用单元中.一两个月之后,您修改了一个不同的模块,您认为您需要在2个月前编写的相同功能.您必须找到该模块(如果您不记得它是哪个模块很困难)并将该功能复制到您的代码中.显然 - 只要每个模块中的一般使用单元分别存储在每个模块中,它们就会完全不同.然后,如果有一个错误修复要做...整个故事重复.

  • 为所有共享代码创建BPL,但将它们链接到EXE,以便EXE是独立的.

对我来说,这似乎是现在最好的解决方案,但有几个缺点.如果我在BPL中修复错误,每个程序员都必须更新他们计算机上的BPL.如果他们忘了怎么办?但是,我认为这是一个小问题.如果我们负责通知对方有关变化,一切都应该没问题.

  • @CodeInChaos:我不知道我是否理解你.你的意思是在项目之间共享pas文件?怎么做?我们在SVN中存储源代码.这意味着我们必须将共享代码存储在单独的文件夹中,并使所有项目在那里搜索该代码,对吧?并从SVN下载一个项目及其依赖的所有文件夹......

请帮我选择一个好的解决方案.我只是因为一种愚蠢的软件开发方法,我不希望公司因错误修正而损失更多的时间和金钱.

非常感谢你.

delphi bpl

11
推荐指数
2
解决办法
3293
查看次数

Delphi中模块化编程的最佳方法

这是我在这里开始的讨论的延续.我想找到模块化Delphi源代码的最佳方法,因为我在这个领域没有经验.我将感激你的所有建议.

让我发布我在那里写的内容.

我工作的公司开发的软件包含100多个模块(大多数模块类似于不同设备的驱动程序).他们中的大多数共享相同的代码 - 在大多数情况下是类.问题是这些类并不总是放在单独的独立PAS单元中.我的意思是共享代码通常放在包含特定于模块的代码的单元中.这意味着当您修复共享类中的错误时,将其定义的PAS单元复制到所有软件模块并重新编译它们是不够的.不幸的是,您必须将固定的代码片段逐个复制并粘贴到每个模块中,并将其粘贴到适当的单元和类中.这需要花费很多时间,这是我希望通过选择正确的方法在最近的将来消除 - 请帮助我.

我认为使用与EXE一起分发的BPL将是一个很好的解决方案,但它有一些缺点,正如前面讨论中提到的那些.最糟糕的问题是,如果每个EXE需要几个BPL,我们的技术支持人员将不得不知道哪个EXE需要哪个BPL,然后为最终用户提供适当的文件.只要我们没有软件更新程序,这对我们的技术人员和最终用户来说都是一个很大的优势.他们肯定会迷茫和愤怒: - /.

此外,还可能出现兼容性问题 - 如果许多EXE共享一个BPL,则对该BPL的修改可能对一个EXE有利,对另一个EXE则有害.

那么我应该怎么做才能在这么多项目中更快地修复错误?我想到了以下方法之一.如果您有更好的想法,请告诉我.

  • 将共享代码放入单独的独立PAS单元中,因此当其中一个中存在错误修复时,将其复制到所有项目(覆盖旧文件)并重新编译所有项目就足够了.这意味着每个单元的复制次数与其使用的项目数相同.

就很少修改的代码而言,这个解决方案似乎没问题.但我们也有具有一般使用功能和程序的通行单元,这些功能和程序经常进行修改.每次有人向此文件添加新功能时,都不可能执行相同的程序(复制和重新编译这么多项目).

  • 为所有共享代码创建BPL,但将它们链接到EXE,以便EXE是独立的.

对我来说,这似乎是现在最好的解决方案,但有一些缺点.如果我在BPL中修复错误,每个程序员都必须在他们的计算机上更新BPL.如果他们忘记那样做怎么办?但是,我认为这是一个小问题.如果我们负责通知对方有关变化,一切都应该没问题.你怎么看?

  • CodeInChaos建议的最后一个想法(我不知道我是否理解它).在项目之间共享PAS文件.这可能意味着我们必须将共享代码存储在一个单独的文件夹中,并让所有项目在那里搜索该代码,对吧?每当有必要修改项目时,我想必须从SVN下载共享文件文件夹.共享代码中的每个更改都必须导致重新编译使用该代码的每个项目.

请帮我选择一个好的解决方案.我只是因为一种愚蠢的软件开发方法,我不希望公司在错误修正方面损失比必要的更多的时间和金钱.到目前为止,没有人关心它,你可以想象它会导致多少问题.

非常感谢你.

delphi bpl modularization

11
推荐指数
1
解决办法
2312
查看次数

控件'xxx'没有父窗口

我正在尝试在Delphi中编写一个dll库,该函数创建一个TFrame后代的实例并返回它.但是当我在一个应用程序中导入这个函数时,每次调用它时我都会得到一个例外,例如"'xxx'控件没有父窗口".我不是百分百肯定,但是当访问任何GUI控件时,该类的构造函数中出现异常.

你能告诉我这种行为的原因是什么吗?我应该只使用TForm后代还是有更好的解决方案?

谢谢!

delphi dll tframe

10
推荐指数
1
解决办法
1万
查看次数

Delphi .res文件更换器

我正在寻找一个可以读取和修改Delphi .res文件的现成代码.问题是我需要创建一个应用程序,它将同时编译许多Delphi项目(使用dcc32.exe文件).但是,我必须在编译之前更改文件版本和语言,据我所知,我必须修改.res文件才能执行此操作.

您是否遇到过任何可以为我提供.res文件接口的代码,允许我修改其中包含的数据?问题是我只想改变那两条信息,保持其余部分不变.这就是我无法根据脚本编译自己的.res文件的原因.

如果允许使用参数调用并执行我需要它执行的操作,则从命令行执行的应用程序也可以.

非常感谢您提前!

delphi resources file

8
推荐指数
1
解决办法
4672
查看次数

Delphi - 调整线程休眠时间

我的应用程序中有几个线程在后台运行.它们连接到数据库并执行一些耗时的选择查询.在大多数情况下,这些查询只返回几条记录.然而,有时他们可能会返回数万条记录.然后将所有这些循环处理.

因为这种情况可能同时发生在多个线程中,所以我不希望我的应用程序在这些线程处理数据时使用100%的CPU时间; 我也不想让所有线程争夺处理器的时间.因此,我在这些线程中的循环的每次迭代中调用Sleep()函数.

但是,我不知道如何调整睡眠时间.我不希望循环永远持续,所以睡眠时间不能太长.我在每次迭代中将它设置为2毫秒(在每个线程中)(为什么2ms? - 这是一个很好的问题:)).

另一方面,我认为我可以延长睡眠时间,但每n次迭代只调用一次睡眠(比方说,每50次迭代睡眠(100次)).我应该选择哪种方法?循环的一次迭代每次约30毫秒(没有任何睡眠).

请指教.

谢谢!
马里乌什.

database delphi multithreading sleep

7
推荐指数
1
解决办法
5354
查看次数