C#在'using'语句中调用'BackgroundWorker'是否安全?

时间:2015-02-03 12:00:12

标签: c# windows-services backgroundworker

我开发了一个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);
    }
}

代码在测试期间工作正常。

我的问题是我做得对吗?

或者这样做有什么问题吗?

由于

3 个答案:

答案 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();
}