C#打电话'安全吗;后台工作人员';内部';使用';陈述

C#打电话'安全吗;后台工作人员';内部';使用';陈述,c#,windows-services,backgroundworker,C#,Windows Services,Backgroundworker,我开发了一个windows服务。在服务中,我使用BackgroundWorker在我的数据库中发布数据。 我在数据库构造函数类中声明了一个BackgroundWorker,并在需要时使用它。 在测试过程中,我遇到了一个错误: 此BackgroundWorker当前正忙,无法运行多个任务 同时 我试图找出解决方案,许多人建议为每个任务使用新实例。我更改了代码,如下所示: ... using (BackgroundWorker bw = new BackgroundW

我开发了一个windows服务。在服务中,我使用BackgroundWorker在我的数据库中发布数据。 我在数据库构造函数类中声明了一个BackgroundWorker,并在需要时使用它。 在测试过程中,我遇到了一个错误:

此BackgroundWorker当前正忙,无法运行多个任务 同时

我试图找出解决方案,许多人建议为每个任务使用新实例。我更改了代码,如下所示:

        ...
        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是最大的障碍。当前的趋势是为每个工作单元创建一个新的
任务
。创建
任务
需要从操作系统租用信号量,但性能是可以接受的。为什么会这样?它们封装的异步工作通常要贵几个数量级——相比之下,设置时间比较便宜。