在后台任务完成之前如何防止前进?

时间:2010-10-15 00:50:05

标签: c# winforms multithreading c#-3.0 synchronization

我有一个外部库,它有一个在后台线程上执行长时间运行任务的方法。完成后,它会触发启动方法的线程上的Completed事件(通常是UI线程)。它看起来像这样:

public class Foo
{
    public delegate void CompletedEventHandler(object sender, EventArgs e);
    public event CompletedEventHandler Completed;

    public void LongRunningTask()
    {
        BackgroundWorker bw = new BackgroundWorker();
        bw.DoWork += new DoWorkEventHandler(bw_DoWork);
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
        bw.RunWorkerAsync();
    }

    void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        Thread.Sleep(5000);
    }

    void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (Completed != null)
            Completed(this, EventArgs.Empty);
    }
}

调用此库的代码如下所示:

private void button1_Click(object sender, EventArgs e)
{
    Foo b = new Foo();
    b.Completed += new Foo.CompletedEventHandler(b_Completed);
    b.LongRunningTask();

    Debug.WriteLine("It's all done");    
}

void b_Completed(object sender, EventArgs e)
{
    // do stuff
}

在button1_Click方法中,在我调用b.LongRunningTask()之后,完成事件在UI线程上5秒后触发,我更新了UI,一切都很棒,因为我不需要处理封送东西到适当的线程。

但是,我现在需要将进程同步(不更改外部库)。换句话说,在我启动.LongRunningTask方法之后,该方法中的下一个有意义的语句应该在.LongRunningTask完成之后触发。

我已尝试使用EventWaitHandle(例如在调用LongRunningTask之后执行WaitOne,然后在Completed事件中重置它,但这只是锁定所有内容)。

.NET框架中是否有允许我这样做的方法?

1 个答案:

答案 0 :(得分:4)

  

我已尝试使用EventWaitHandle(例如在调用LongRunningTask之后执行WaitOne,然后在Completed事件中重置它,但这只是锁定了所有内容)。

如果按照定义进行同步,那么这正是会发生的事情。如果不阻止UI线程,就无法使其同步。

在操作之后,您不需要触发“该方法中的下一个有意义的语句”,而是需要阻止它,或者在回调中触发有意义的语句。