ThreadPool和GUI等问题

时间:2008-12-17 17:23:35

标签: c# threadpool deadlock

我是线程新手,需要帮助。我有一个数据录入应用程序需要花费过多的时间来插入一个新的记录(即50-75秒)。所以我的解决方案是通过ThreadPool发送一个insert语句,并允许用户开始输入记录的数据,同时插入在该插入运行时返回一个新的记录ID。我的问题是用户可以在从该插入返回新ID之前点击保存。

我尝试输入一个布尔变量,当安全保存时,该变量通过该线程中的事件设置为true。然后我放入

while (safeToSave == false)  
{  
    Thread.Sleep(200)  
}  

我认为这是一个坏主意。如果我在该胎面返回之前运行保存方法,它就会卡住。

所以我的问题是:

  1. 有更好的方法吗?
  2. 我在这里做错了什么?
  3. 感谢您的帮助 道格

    修改以获取更多信息:

    它正在插入一个非常大(接近最大大小)的FoxPro数据库。该文件有大约200个字段,其上的索引几乎一样多 在你问之前,我不能改变它的结构,因为它在我之前就已存在,并且有大量的遗留代码。第一个问题是,为了获得一个新的ID,我必须首先在表中找到max(id)然后递增并校验它。大约需要45秒。然后第一个插入就是简单地插入新的id和一个enterdate字段。此表不能/不能放入DBC,以排除自动生成ID等。

    @ joshua.ewer
    你有正确的过程,我认为短期内我只会禁用保存按钮,但我会考虑你把它传递到队列的想法。你有任何关于MSMQ的参考我应该看看吗?

5 个答案:

答案 0 :(得分:2)

1)很多:),例如你可以在线程插入对象时禁用“保存”按钮,或者你可以设置一个处理“保存请求”队列的线程工作者(但我想这里的问题)是用户想要修改新创建的记录,因此禁用该按钮可能更好)

2)我认为我们需要更多的代码才能理解......(或者可能是同步问题,我也不是线程的漏洞粉丝)

顺便说一句,我只是不明白为什么插入应该花这么长时间..我认为你应该先检查一下代码! < - 正如查尔斯之前所说的那样(对不起,请不要阅读帖子):)

答案 1 :(得分:1)

其他人,包括你在内,都解决了核心问题(插入时间,你为什么要插入,然后更新),所以我会坚持你提出的解决方案的技术问题。所以,如果我得到正确的流程:

  • 主题1:开始输入数据 记录

  • 线程2:后台调用DB以检索新的Id

  • 始终启用保存按钮, 如果用户尝试在Thread之前保存 2完成后,你把#1睡觉了 200毫秒?

最简单但不是最好的答案就是禁用该按钮,让该线程向启用该按钮的委托制作callback。在确定设置正确之前,他们无法启动更新操作。

尽管如此,我认为一个更好的解决方案(如果你只是为FoxPro构建Q& D前端可能会夸大其词),那就是将这些保存操作放入队列中。用户可以尽快键入,然后将请求放入类似MSMQ的内容中,并且可以在他们自己的时间内异步完成。

答案 2 :(得分:1)

使用future而不是原始的ThreadPool操作。执行未来,允许用户做任何他们想做的事情,当他们点击第二条记录上的Save时,请求将来的值。如果第一个插入已经完成,您将立即获得ID,并允许第二个插入开始。如果您仍在等待第一个操作,则将来将阻塞,直到它可用,然后第二个操作可以执行。

除非用户比操作慢,否则您不会保存任何时间。

答案 3 :(得分:0)

首先,您应该找出并修复插件花费这么长时间的原因... 50-75秒对于单行插入的任何现代数据库都是不合理的,并且表明还需要其他东西解决,像索引,或阻止......

其次,为什么在获取数据之前插入记录?通常,对数据输入应用程序进行编码,以便在从用户收集插入的所有必要数据之前不尝试插入。你这样做是因为你试图先从数据库中获取新的Id,然后用用户输入的数据“更新”新的空记录吗?如果是这样,几乎每个数据库供应商都有一种机制,您可以在不知道新ID的情况下只执行一次插入,并让数据库返回新ID ...您使用的是哪个供应商数据库?

答案 4 :(得分:0)

这样的解决方案是否可行:

在用户开始添加之前预先计算唯一ID。保留表中已有的唯一ID列表,但它们实际上是占位符。当用户尝试插入时,保留其中一个唯一ID,当用户按下save时,他们现在用他们的数据替换占位符。

PS:很难确认这一点,但要注意以下并发问题与你提出的建议(有或没有线程):用户A,开始添加,用户B开始添加,用户A计算ID 1234为最大空闲ID,用户B计算ID 1234作为最大空闲ID。用户A插入ID 1234,用户B插入ID 1234 = Boom!