我开发了一个Windows服务。在服务中,我使用BackgroundWorker在我的数据库中发布数据。 我在我的数据库构造函数类中声明了BackgroundWorker,并在需要时使用它。 在测试期间,我收到一个错误:
此BackgroundWorker当前正忙,无法运行多个任务 同时
我试图找出解决方案,许多人建议为每个任务使用新实例。我改变了我的代码:
...
using (BackgroundWorker bw = new BackgroundWorker())
{
bw.DoWork += new DoWorkEventHandler(bkDoPost);
bw.RunWorkerAsync(dbobj);
}
...
和我的' bkDoPost'是:
void bkDoPost(object sender, DoWorkEventArgs e)
{
try
{
dbObject dbj = e.Argument as dbObject;
this.db.Insert(dbj.tableName, dbj.data);
}
catch (Exception ex)
{
logs.logMessage("There was an error in data post. See the ErrorLog");
logs.logError(ex);
}
}
代码在测试期间工作正常。
我的问题是我做得对吗?
或者这样做有什么问题吗?
由于
答案 0 :(得分:2)
最好在工作完成后手动调用Dispose
。
更好的是,考虑使用不同的方案来处理异步工作。后台工作者正在变得过时,并且针对UI应用程序而不是服务。对并行操作的限制强调了课程的意图。
答案 1 :(得分:0)
不要将BackgroundWorker放入using语句中。而是将Dispose()调用放入RunWorkerCompleted事件中。
然而,在你的情况下,BackgroundWorker可能不是最好用的,因为它是一种非常好的用法,即在UI保持响应的同时运行一些商业代码并在RunWorkerCompeleted事件中自动更新UI。
如果您在作业完成时不需要干扰UI,或者您要完成大量小工作,那么切换到Task
内的工作封装会更有效率。< / p>
答案 2 :(得分:0)
如果您有许多更新,那么为每个更新创建一个BackgroundWorker可能会耗费大量时间和内存 我会使用一个独立的线程,每次必须进行更新时我都会醒来:
Queue<DbWork> dbUpdates = new Queue<DbWork>();
EventWaitHandle waiter = new EventWaitHandle(false, EventResetMode.ManualReset);
...
// Init :
new Thread(new ThreadStart(DbUpdateWorker));
...
private void DbUpdateWorker()
{
while (true)
{
DbWork currentWork = null;
lock (dbUpdates)
{
if (dbUpdates.Count > 0)
currentWork = dbUpdates.Dequeue();
}
if (currentWork != null)
{
currentWork.DoWork();
}
if (dbUpdates.Count == 0)
{
waiter.WaitOne();
}
}
}
public void AddWork(DbWork work)
{
lock (dbUpdates)
{
dbUpdates.Enqueue(work);
}
waiter.Set();
}