C# 暂停新的BackGroundWorker,直到上一个完成

C# 暂停新的BackGroundWorker,直到上一个完成,c#,.net,wpf,multithreading,C#,.net,Wpf,Multithreading,我正在努力解决线程问题。 问题是当我通过foreach循环迭代时 设置此.Document时,应用程序将执行登录,该操作由事件触发,需要几秒钟才能完成。在worker\u RunWorkerCompleted方法中,我需要根据当前登录信息执行一些操作 问题是,在我可以对第一个文件执行此操作之前,this.Document已经更改,使应用程序执行另一次登录。这样的话,我就永远不能真正地执行我的行为 我的问题是:如何暂停下一个线程,直到上一个线程完成。 我的问题还有别的解决办法吗 我尝试了AutoR

我正在努力解决线程问题。 问题是当我通过foreach循环迭代时

设置
此.Document
时,应用程序将执行登录,该操作由事件触发,需要几秒钟才能完成。在
worker\u RunWorkerCompleted
方法中,我需要根据当前登录信息执行一些操作

问题是,在我可以对第一个文件执行此操作之前,
this.Document
已经更改,使应用程序执行另一次登录。这样的话,我就永远不能真正地执行我的行为

我的问题是:如何暂停下一个线程,直到上一个线程完成。 我的问题还有别的解决办法吗

我尝试了
AutoResetEvent
,但没有成功。我在RunWorkerAsync调用之后设置了
waitOne()
,并在RunWorkerCompleted中设置了
.set()
。代码永远不会到达
RunWorkerCompleted

代码如下:

    public void Start(object obj)
    {
       try
       {
          foreach (KeyValuePair<string, Stream> pair in this.CollectionOfFiles)
          {
              Worker = new BackgroundWorker();
              Worker.DoWork += new DoWorkEventHandler(worker_DoWork);
              Worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);

          using (Stream stream = pair.Value)
              {
                primaryDocument = new Document(stream);

                DataHolderClass dataHolder = new DataHolderClass();
                dataHolder.FileName = pair.Key;
                dataHolder.Doc = secondaryDocument;

               //background thread call
                Worker.RunWorkerAsync(dataHolder);
              }
            }
          }

       catch (Exception ex)
       {
          // exception logic
}
       finally
       {
          // complete logic
       }
    }


    private void worker_DoWork(object sender, DoWorkEventArgs e)
    {
       DataHolderClass dataHolder = ((DataHolderClass)e.Argument);
       // setting this attribute triggers execution of login event
       this.Document = dataHolder.Doc;
       e.Result = (dataHolder);
    }


    private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
       // here I need to perform some actions that are depending on the current login
       DataHolderClass dataHolder = ((DataHolderClass)e.Result);
       this.eventAggregator.GetEvent<ActionEvent>().Publish(new Message(EMessageType.Info) { Title = dataHolder.FileName });
    }
公共作废开始(对象obj)
{
尝试
{
foreach(此.CollectionOfFiles中的KeyValuePair对)
{
Worker=新的BackgroundWorker();
Worker.DoWork+=新的doworkereventhandler(Worker\u DoWork);
Worker.RunWorkerCompleted+=新的RunWorkerCompletedEventHandler(Worker\u RunWorkerCompleted);
使用(Stream=pair.Value)
{
primaryDocument=新文档(流);
DataHolderClass dataHolder=新DataHolderClass();
dataHolder.FileName=pair.Key;
dataHolder.Doc=第二个文档;
//后台线程调用
Worker.RunWorkerAsync(数据持有者);
}
}
}
捕获(例外情况除外)
{
//异常逻辑
}
最后
{
//完全逻辑
}
}
私有void worker_DoWork(对象发送方,DoWorkEventArgs e)
{
DataHolderClass dataHolder=((DataHolderClass)e.Argument);
//设置此属性将触发登录事件的执行
this.Document=dataHolder.Doc;
e、 结果=(数据持有者);
}
私有void worker\u RunWorkerCompleted(对象发送方,RunWorkerCompletedEventArgs e)
{
//在这里,我需要根据当前登录执行一些操作
DataHolderClass dataHolder=((DataHolderClass)e.Result);
this.eventAggregator.GetEvent().Publish(新消息(EMessageType.Info){Title=dataHolder.FileName});
}
第9条

请尝试以下操作:

System.Threading.ManualResetEvent _busy = new System.Threading.ManualResetEvent(false);

void ResumeWorker() 
{
     // Start the worker if it isn't running
     if (!backgroundWorker1.IsBusy) backgroundWorker1.RunWorkerAsync(dataHolder);  
     // Unblock the worker 
     _busy.Set();
}

void PauseWorker() 
{
    // Block the worker
    _busy.Reset();
}

void CancelWorker() 
{
    if (backgroundWorker1.IsBusy) {
        // Set CancellationPending property to true
        backgroundWorker1.CancelAsync();
        // Unblock worker so it can see that
        _busy.Set();
    }
}
然后在代码中运行该方法

让我知道它是否有效:)

你会用脉搏吗?
摘自:

嗯,设计很糟糕。。。但如果您需要坚持使用它,您可以在前一个worker中设置等待句柄,并在下一个worker中等待它。这是最基本的解决方案,仍然是一个令人憎恶的问题:

public void Start(object obj)
{
    try
    {
        BackgroundWorker previousWorker = null;
        DataHolderClass previousWorkerParams = null;

        foreach (KeyValuePair<string, Stream> pair in this.CollectionOfFiles)
        {
            // signal event on previous worker RunWorkerCompleted event
            AutoResetEvent waitUntilCompleted = null;
            if (previousWorker != null)
            {
                waitUntilCompleted = new AutoResetEvent(false);
                previousWorker.RunWorkerCompleted += (o, e) => waitUntilCompleted.Set();

                // start the previous worker
                previousWorker.RunWorkerAsync(previousWorkerParams);
            }

            Worker = new BackgroundWorker();

            Worker.DoWork += (o, e) =>
            {
                // wait for the handle, if there is anything to wait for
                if (waitUntilCompleted != null)
                {
                    waitUntilCompleted.WaitOne();
                    waitUntilCompleted.Dispose();
                }
                worker_DoWork(o, e);
            };

            using (Stream stream = pair.Value)
            {
                primaryDocument = new Document(stream);

                DataHolderClass dataHolder = new DataHolderClass();
                dataHolder.FileName = pair.Key;
                dataHolder.Doc = secondaryDocument;

                // defer running this worker; we don't want it to finish
                // before adding additional completed handler
                previousWorkerParams = dataHolder;
            }

            previousWorker = Worker;
        }

        if (previousWorker != null)
        {
            previousWorker.RunWorkerAsync(previousWorkerParams);
        }
    }

    catch (Exception ex)
    {
        // exception logic
    }
    finally
    {
        // complete logic
    }
}
公共作废开始(对象obj)
{
尝试
{
BackgroundWorker-previousWorker=null;
DataHolderClass previousWorkerParams=null;
foreach(此.CollectionOfFiles中的KeyValuePair对)
{
//上一个worker RunWorkerCompleted事件上的信号事件
AutoResetEvent WaitUntillCompleted=null;
if(previousWorker!=null)
{
waitUntilCompleted=新自动重置事件(假);
previousWorker.RunWorkerCompleted+=(o,e)=>WaitUntillCompleted.Set();
//启动上一个工作进程
previousWorker.RunWorkerAsync(previousWorkerParams);
}
Worker=新的BackgroundWorker();
Worker.DoWork+=(o,e)=>
{
//如果有什么需要等待的,请等待手柄
如果(WaitUntillCompleted!=null)
{
waituntlcompleted.WaitOne();
waituntlcompleted.Dispose();
}
工人工作(o、e);
};
使用(Stream=pair.Value)
{
primaryDocument=新文档(流);
DataHolderClass dataHolder=新DataHolderClass();
dataHolder.FileName=pair.Key;
dataHolder.Doc=第二个文档;
//推迟运行此worker;我们不希望它完成
//在添加其他已完成的处理程序之前
previousWorkerParams=数据持有者;
}
以前的工人=工人;
}
if(previousWorker!=null)
{
previousWorker.RunWorkerAsync(previousWorkerParams);
}
}
捕获(例外情况除外)
{
//异常逻辑
}
最后
{
//完全逻辑
}
}

它是在Worker.RunWorkerAsync(数据持有者)运行时生成的;又被击中了…我没弄错吧?设置文档触发器是否以某种方式启动?不是。。。设置文档会触发登录操作(此处未显示)。当我在worker\u Runworker Completed中时,我需要执行一些检查登录的操作。登录只需几秒钟即可完成,这是一个基于事件的调用。我的情况是,当我到达worker\u RunWorker完成时,登录名已经更改,因为集合中的另一项设置了此。文档…哦,天哪,您的竞争条件太糟糕了。如果您一次记录多次日志(有意吗?),为什么要使用单个(this.Document)属性?这个设计看起来很奇怪。如果
RunWorkerCompleted
需要当前登录,那么在同一个线程中执行它们。如果它们在不同的线程中,那么当然一个线程可以在另一个线程之前完成,这就是线程的设计目的。。。
public void Start(object obj)
{
    try
    {
        BackgroundWorker previousWorker = null;
        DataHolderClass previousWorkerParams = null;

        foreach (KeyValuePair<string, Stream> pair in this.CollectionOfFiles)
        {
            // signal event on previous worker RunWorkerCompleted event
            AutoResetEvent waitUntilCompleted = null;
            if (previousWorker != null)
            {
                waitUntilCompleted = new AutoResetEvent(false);
                previousWorker.RunWorkerCompleted += (o, e) => waitUntilCompleted.Set();

                // start the previous worker
                previousWorker.RunWorkerAsync(previousWorkerParams);
            }

            Worker = new BackgroundWorker();

            Worker.DoWork += (o, e) =>
            {
                // wait for the handle, if there is anything to wait for
                if (waitUntilCompleted != null)
                {
                    waitUntilCompleted.WaitOne();
                    waitUntilCompleted.Dispose();
                }
                worker_DoWork(o, e);
            };

            using (Stream stream = pair.Value)
            {
                primaryDocument = new Document(stream);

                DataHolderClass dataHolder = new DataHolderClass();
                dataHolder.FileName = pair.Key;
                dataHolder.Doc = secondaryDocument;

                // defer running this worker; we don't want it to finish
                // before adding additional completed handler
                previousWorkerParams = dataHolder;
            }

            previousWorker = Worker;
        }

        if (previousWorker != null)
        {
            previousWorker.RunWorkerAsync(previousWorkerParams);
        }
    }

    catch (Exception ex)
    {
        // exception logic
    }
    finally
    {
        // complete logic
    }
}