我有一个计时器和一个后台工作器,它会在每个计时器时间点启动。有时我需要用户停止此工作流程并通过单击按钮调用相同的bg worker。
因为它在Silverlight中所有都是异步的。 BG工作人员进行异步Webservice调用,异步返回数据。 我这样做了,但感觉不对。处理这种情况的最佳方法是什么?
button_click_event(..)
{
_loadTimer.Stop();
_worker.CancelAsync();
_worker.RunWorkerAsync();
}
WebService调用
public void GetUserStats(DateTime start, DateTime end, Action<IEnumerable<IUserStats>, Exception> callback)
{
_context.GetUserStatsCompleted += ContextGetUserStatsCompleted;
_context.GetUserStatsAsync(start,end,callback);
}
void ContextGetUserStatsCompleted(object sender, GetUserStatsCompletedEventArgs e)
{
var callback = e.UserState as Action<IEnumerable<IUserStats>, Exception>;
Exception error = null;
var result = new ObservableCollection<IUserStats>();
if (e.Error == null)
{
result = e.Result;
}
else
{
error = e.Error;
}
_context.GetUserStatsCompleted -= ContextGetUserStatsCompleted;
callback(result, error);
}
和我的工作人员
void WorkerDoWork(object sender, DoWorkEventArgs e)
{
TicketService.GetUserStats(StartDate, EndDate, (result, error) =>
{
StreamHolder = result;
});
}
答案 0 :(得分:4)
首先,在尝试再次运行之前,应始终检查您的工作人员是否正在运行。如果不这样做,那么您的应用程序可能会抛出异常。
if(!_worker.IsBusy)
{
_worker.RunWorkerAsync();
}
其次,仅调用CancelAsync()不足以取消后台工作程序的当前操作。您必须将代码添加到后台工作程序的DoWork事件处理程序。 (在你的情况下是WorkerDoWork)
if(_worker.CancelationPending == true)
{
e.Cancel = true;
return;
}
您可以在此处详细了解使用后台工作程序的正确方法:
http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx