C# 如何防止在后台任务完成之前向前移动?

C# 如何防止在后台任务完成之前向前移动?,c#,winforms,multithreading,c#-3.0,synchronization,C#,Winforms,Multithreading,C# 3.0,Synchronization,我有一个外部库,它有一个在后台线程上执行长时间运行任务的方法。完成后,它会在启动该方法的线程(通常是UI线程)上触发一个已完成事件。看起来是这样的: public class Foo { public delegate void CompletedEventHandler(object sender, EventArgs e); public event CompletedEventHandler Completed; public void LongRunningTa

我有一个外部库,它有一个在后台线程上执行长时间运行任务的方法。完成后,它会在启动该方法的线程(通常是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
}
调用此库的代码如下所示:

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()之后,完成的事件在5秒后在UI线程上触发,我更新了UI,一切都很好,因为我不必处理将内容封送到适当的线程

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

我曾经尝试过使用EventWaitHandle(例如,在调用LongRunningTask后执行WaitOne,然后在已完成的事件中重置它,但这只会锁定所有内容)

在.NET framework中是否有一种方法允许我这样做

我曾经尝试过使用EventWaitHandle(例如,在调用LongRunningTask后执行WaitOne,然后在已完成的事件中重置它,但这只会锁定所有内容)

根据定义,如果你让它同步,那将会发生什么。如果不阻塞UI线程,就无法使其同步

您需要使其阻塞,或者在回调中激发有意义的语句,而不是在操作后激发“该方法中的下一个有意义语句”

我曾经尝试过使用EventWaitHandle(例如,在调用LongRunningTask后执行WaitOne,然后在已完成的事件中重置它,但这只会锁定所有内容)

根据定义,如果你让它同步,那将会发生什么。如果不阻塞UI线程,就无法使其同步


您需要使其阻塞,或者让有意义的语句在回调中激发,而不是在操作后激发“该方法中的下一个有意义语句”。

如果我阻塞UI线程,库中的BackgroundWorker将无法激发UI线程上发生的RunWorkerCompleted事件。因此,应用程序将被挂起。Background worker最初的设计思想是,它可以从UI层启动异步进程,然后在完成事件时启动。@AngryHacker:除非在此之前取消阻止,在后台线程中。@Jim:是的-在同步场景中使用BW只是在制造麻烦。如果我阻止UI线程,库中的BackgroundWorker将无法触发RunWorkerCompleted事件,该事件发生在UI线程上。因此,应用程序将被挂起。Background worker最初的设计思想是,它可以从UI层启动异步进程,然后在完成事件时启动。@AngryHacker:除非在此之前取消阻止,在后台线程中。@Jim:是的-在同步场景中使用BW只是在制造麻烦。我想看看从库中序列化回调到主线程的代码。我尝试过这样做,但失败了——在我看来,您应该为此发送更多的参数——至少是稍后用于Invoke()的控件?我想看看将回调从库序列化到主线程的代码。我尝试过做这样的事情,但失败了——在我看来,您应该为此发送更多参数——至少是稍后将用于Invoke()的控件?