我挣扎与线程。 问题是,当我遍历低谷foreach循环。
当设定 this.Document
,应用程序执行登录,即触发一个事件,并采取几秒钟即可完成。在 worker_RunWorkerCompleted
方法,我需要执行依赖于当前的登录信息的一些行动。
现在的问题是,在我能第一个文件执行此操作时, this.Document
已经改变提出申请执行另一个登录。这样我可以从来没有真正执行我的行动。
我的问题是:我怎样才能暂停下一个线程,直到previous线程完成。 是否有任何其他解决我的问题?
我试着用的AutoResetEvent
,但我没有运气。我设置 WaitOne的()
只是在RunWorkerCompleted中的RunWorkerAsync通话和。设置()
之后。在code永远不会到达 RunWorkerCompleted
...
下面是code:
公共无效启动(obj对象)
{
尝试
{
的foreach(KeyValuePair<字符串,流>对在this.CollectionOfFiles)
{
工人=新的BackgroundWorker();
Worker.DoWork + =新DoWorkEventHandler(worker_DoWork);
Worker.RunWorkerCompleted + =新RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
使用(流流= pair.Value)
{
primaryDocument =新的文件(流);
DataHolderClass dataHolder =新DataHolderClass();
dataHolder.FileName = pair.Key;
dataHolder.Doc = secondaryDocument;
//后台线程调用
Worker.RunWorkerAsync(dataHolder);
}
}
}
赶上(例外前)
{
//异常逻辑
}
最后
{
//完整的逻辑
}
}
私人无效worker_DoWork(对象发件人,DoWorkEventArgs E)
{
DataHolderClass dataHolder =((DataHolderClass)e.Argument);
//设置该属性触发执行登录事件
this.Document = dataHolder.Doc;
e.Result =(dataHolder);
}
私人无效worker_RunWorkerCompleted(对象发件人,RunWorkerCompletedEventArgs E)
{
//这里我需要执行的根据当前登录的一些动作
DataHolderClass dataHolder =((DataHolderClass)e.Result);
this.eventAggregator.GetEvent< ActionEvent的>()发布(新消息(EMessageType.Info){标题= dataHolder.FileName})。
}
解决方案
那么,设计是可怕的......不过的如果的你的需要的坚持下去,你可以设置等候在previous工人把手,并等待它的下一个。这是基本修复,还是相当可憎的:
公共无效启动(obj对象)
{
尝试
{
BackgroundWorker的previousWorker = NULL;
DataHolderClass previousWorkerParams = NULL;
的foreach(KeyValuePair<字符串,流>对在this.CollectionOfFiles)
{
//在previous工人RunWorkerCompleted事件信号事件
的AutoResetEvent waitUntilCompleted = NULL;
如果(previousWorker!= NULL)
{
waitUntilCompleted =新的AutoResetEvent(假);
previousWorker.RunWorkerCompleted + =(O,E)=> waitUntilCompleted.Set();
//开始previous工人
previousWorker.RunWorkerAsync(previousWorkerParams);
}
工人=新的BackgroundWorker();
Worker.DoWork + =(O,E)=>
{
//等待手柄,如果有任何等待
如果(waitUntilCompleted!= NULL)
{
waitUntilCompleted.WaitOne();
waitUntilCompleted.Dispose();
}
worker_DoWork(O,E);
};
使用(流流= pair.Value)
{
primaryDocument =新的文件(流);
DataHolderClass dataHolder =新DataHolderClass();
dataHolder.FileName = pair.Key;
dataHolder.Doc = secondaryDocument;
//推迟执行该工作人员;我们不希望它完成
前//添加额外的完成处理程序
previousWorkerParams = dataHolder;
}
previousWorker =工人;
}
如果(previousWorker!= NULL)
{
previousWorker.RunWorkerAsync(previousWorkerParams);
}
}
赶上(例外前)
{
//异常逻辑
}
最后
{
//完整的逻辑
}
}
I am struggling with threading. The problem is when I am iterating trough foreach loop.
When setting this.Document
, the application performs login, that is triggered with an event and takes few seconds to complete. In the worker_RunWorkerCompleted
method I need to perform some actions that depend on current login information.
The problem is that before I can perform this action for the first file, the this.Document
already changes making the application perform another login. This way I can never actually perform my actions.
My question is: How can I pause the next thread until previous thread has completed. Is there any other solution to my problem?
I tried with AutoResetEvent
but I got no luck. I set waitOne()
just after the RunWorkerAsync call and .Set()
in the RunWorkerCompleted. The code never gets to RunWorkerCompleted
...
Here is the code:
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 });
}
解决方案
Well, the design is terrible... but if you need to stick to it, you can set wait handles in a previous worker and wait for it in next. This is the minimal fix, still quite an abomination:
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
}
}
上一篇:无法推出Android应用程序在Eclipse中;期间发生内部错误:&QUOT;启动对myApp&QUOT;应用程序、错误、发生、Android
下一篇:试图与离子构建失败,Android模拟器..&QUOT;找不到类:javac1.8&QUOT;找不到、模拟器、离子、Android