C#打电话'安全吗;后台工作人员';内部';使用';陈述
我开发了一个windows服务。在服务中,我使用BackgroundWorker在我的数据库中发布数据。 我在数据库构造函数类中声明了一个BackgroundWorker,并在需要时使用它。 在测试过程中,我遇到了一个错误: 此BackgroundWorker当前正忙,无法运行多个任务 同时 我试图找出解决方案,许多人建议为每个任务使用新实例。我更改了代码,如下所示:C#打电话'安全吗;后台工作人员';内部';使用';陈述,c#,windows-services,backgroundworker,C#,Windows Services,Backgroundworker,我开发了一个windows服务。在服务中,我使用BackgroundWorker在我的数据库中发布数据。 我在数据库构造函数类中声明了一个BackgroundWorker,并在需要时使用它。 在测试过程中,我遇到了一个错误: 此BackgroundWorker当前正忙,无法运行多个任务 同时 我试图找出解决方案,许多人建议为每个任务使用新实例。我更改了代码,如下所示: ... using (BackgroundWorker bw = new BackgroundW
...
using (BackgroundWorker bw = new BackgroundWorker())
{
bw.DoWork += new DoWorkEventHandler(bkDoPost);
bw.RunWorkerAsync(dbobj);
}
...
我的“BKDOST”是:
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);
}
}
该代码在测试期间运行良好
我的问题是我的做法是否正确
或者这样做有什么问题吗
谢谢,别那么做。在您的工作完成之前,您的后台工作人员将被释放 最好在工作完成后手动调用
Dispose
更好的是,考虑使用不同的方案来处理异步工作。后台工作程序正在变得过时,其目标是UI应用程序,而不是服务。对并行操作的限制突出了类的意图。
不要将BackgroundWorker放入using语句中。而是将Dispose()调用放入RunWorkerCompleted事件中 尽管如此,BackgroundWorker在您的情况下可能不是最好的选择,因为它的主要用途是在UI保持响应的同时运行一些业务代码,并在RunWorkerCompleted事件中自动更新UI如果您不需要在作业完成时干扰UI,或者您有许多较小的作业要完成,那么切换到将作业封装在s中会更有效。如果您有许多更新,为每个更新创建一个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();
}
Queue dbUpdates=new Queue();
EventWaitHandle water=新的EventWaitHandle(false,EventResetMode.ManualReset);
...
//初始化:
新线程(新线程开始(DbUpdateWorker));
...
私有void DbUpdateWorker()
{
while(true)
{
DbWork currentWork=null;
锁定(数据库更新)
{
如果(dbUpdates.Count>0)
currentWork=dbUpdates.Dequeue();
}
if(currentWork!=null)
{
currentWork.DoWork();
}
如果(dbUpdates.Count==0)
{
服务员,等一等;
}
}
}
公共无效添加工作(数据库工作)
{
锁定(数据库更新)
{
dbUpdates.Enqueue(工作);
}
服务员:Set();
}
谢谢@Oliver这是客户端应用程序使用的服务。当它收到请求时,它将信息记录到数据库中,并将响应返回给客户机请求。数据库驻留在远程服务器上,因此可能需要更长的时间来发布数据,这就是我决定在后台发布数据的原因。@lqbal:然后切换到任务。创建新对象不是一个性能问题,除非您真正了解了大量数据。算术和IO是最大的障碍。当前的趋势是为每个工作单元创建一个新的任务。创建任务
需要从操作系统租用信号量,但性能是可以接受的。为什么会这样?它们封装的异步工作通常要贵几个数量级——相比之下,设置时间比较便宜。