全部。 我有一组运行Worker类实例的BackgroundWorker对象。当我调用Worker类时,对象实例会执行它,然后用尽代码(循环结束)。我能够收听RunWorkerCompleted()事件,但是当它调用我设置的委托时,我需要知道我的哪些Worker对象刚刚完成。
我在RunWorkerCompletedEventArgs中看到了一个UserState属性,该属性来自我的委托,但我不知道如何在我的Worker对象中设置它,因为它正在完成。
有什么想法吗?
来自我的WorkManager.cs类的片段
public Worker AddWorker()
{
Worker w = new Worker();
_workers.Add(w.WorkerID,w);
BackgroundWorker bg = new BackgroundWorker();
_bgworkers.Add(bg);
bg.DoWork += w.Start;
bg.WorkerReportsProgress = true;
bg.WorkerSupportsCancellation = true;
bg.ProgressChanged += ProcessWorkerMessage;
bg.RunWorkerCompleted += WorkerFinished;
w.WorkManager = this;
w.BackgroundWorker = bg;
bg.RunWorkerAsync(w);
return w;
}
public void WorkerFinished(object sender, RunWorkerCompletedEventArgs e)
{
if (_onManagerEvent != null)
_onManagerEvent(new ManagerEvent { EventDate = DateTime.Now, Message = "Worker ??? successfully ended." });
}
因此,当我的Worker对象在其Start()方法中完成循环时,我该怎么做才能填充传递给我的WorkerFinished方法()的RunWorkerCompleteEventArgs对象“e”的userState属性?
由于
答案 0 :(得分:13)
Start
类上的Worker
方法可以设置Result
参数的DoWorkEventArgs
属性。这是一个例子:
void Start(object sender, DoWorkEventArgs e)
{
//Do your loop and other work.
e.Result = this;
}
然后在完成事件处理程序中,您可以检索e.Result:
public void WorkerFinished(object sender, RunWorkerCompletedEventArgs e)
{
//You should always check e.Cancelled and e.Error before checking e.Result!
// ... even though I'm skipping that here
Worker w = e.Result as Worker;
if( w != null)
{
if (_onManagerEvent != null)
_onManagerEvent(new ManagerEvent
{
EventDate = DateTime.Now,
Message = String.Format("Worker {0} successfully ended."
, w.ToString())
});
}
}
答案 1 :(得分:3)
UserState
中的BackgroundWorker
事件是RunWorkerCompletedEventArgs.Result
中的已知错误:
http://www.pluralsight-training.net/community/blogs/mike/archive/2005/10/21/15783.aspx(archive.org链接...原始链接已死)
我过去在遇到你的情况时所做的就是使用BackgroundWorker
(如菲利普建议的那样),或者,如果可能的话,让我的工作人员来自BackgroundWorker
(那么我可以添加尽可能多的额外状态,并将整个worker作为Result
引发的事件的sender参数,同时仍然可以将{{1}}用于其预期目的。/ p>
答案 2 :(得分:1)
十五年后,甚至在Microsoft将Winforms移植到.NET Core之后, lesscode 答案中提到的错误仍未得到修复。我还有其他要求,即在取消工作程序时需要获取“用户对象”。
由于在取消工作程序时无法设置该用户对象,并且无法访问结果,因此我不得不与RunWorkerCompletedEventArgs
实现分开跟踪取消操作。
这是我的解决方案。首先,创建一个结果对象,将其作为用户对象承担双重责任(对不起SRP),类似
class WorkerStateAndResult
{
public bool Errored { get; set; }
public bool Canceled { get; set; }
// other state/results...
}
然后,在工作人员的处理程序中,立即将Result
属性设置为WorkerStateAndResult
的实例。在处理程序内部,取消工作程序时,不会将DoWorkEventArgs.Canceled
设置为true
;您将改为在状态对象上设置属性;错误情况也是如此。您的处理程序最终看起来像
private void HandleWorkerDoWork(object sender, DoWorkEventArgs e)
{
var stateAndResult = new WorkerStateAndResult(...);
e.Result = stateAndResult;
try
{
// do the work and check for cancellation. if cancellation happens, set Canceled
// instead of using built-in e.Canceled property
stateAndResult.Canceled = ResultOfActualWork();
}
catch
{
// handle errors, again, not using built-in mechanism
stateAndResult.Error = true;
}
finally
{
// any cleanup
}
}
最后,在RunWorkerCompleted
处理程序中,您可以访问具有所有结果和状态的result,并且可以检查Error
和Canceled
属性以执行任何逻辑操作需要:
private void HandleAnalyzerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// this would normally throw if error or canceled, but not anymore!
var result = (WorkerStateAndResult)e.Result;
if (result.Canceled)
{
// do canceled logic
}
else if (result.Errored)
{
// do error logic
}
else
// do regular logic using result
}