C# 如何使用任务<;T>;引发事件并等待事件完成
我有以下情况:C# 如何使用任务<;T>;引发事件并等待事件完成,c#,multithreading,asynchronous,event-handling,task-parallel-library,C#,Multithreading,Asynchronous,Event Handling,Task Parallel Library,我有以下情况: 请求启动Web服务的客户端 public bool Start(MyProject project, string error) 在方法中从客户端接收调用的web服务 public event EventHandler<StartEventArgs> startEvent; public bool Start(MyProject project, string error) { Task<bool> result = StartAsync(p
public bool Start(MyProject project, string error)
public event EventHandler<StartEventArgs> startEvent;
public bool Start(MyProject project, string error)
{
Task<bool> result = StartAsync(project, error);
return result.Result;
}
protected virtual void OnStart(StartEventArgs e)
{
// thread safe trick, snapshot of event
var se = startEvent;
if (se != null)
{
startEvent(this, e);
}
}
private Task<bool> StartAsync(MyProject project, string error)
{
var taskCompletion = new TaskCompletionSource<bool>();
this.startEvent += (p, e) => taskCompletion.TrySetResult((e.Error == string.Empty) ? true : false);
this.OnStart(new StartEventArgs(project, error));
return taskCompletion.Task;
}
Task<bool> startTask = Task.Factory.StartNew(() => { OnStart() });
startTask.WaitAll(); // I think this is what I would need to for 4.0
return startTask.Result
Task startTask=Task.Factory.StartNew(()=>{OnStart()});
startTask.WaitAll();//我想这就是我需要为4.0做的
返回startTask.Result
我希望我的描述足够让人明白我在做什么。我希望服务不必了解客户机的任何信息,只需运行任务,一旦事件完成执行,返回到此点并向客户机返回表示成功/失败的布尔值
这是可能的还是我采取了一种非常错误的方法
更新:
很明显,OnStart不是一个事件,因此我如何做您试图向我解释的事情?您可以通过将描述基于事件的异步模式的事件包装到
任务中。基本模式通常类似于:
Task<bool> StartAsync()
{
var tcs = new TaskCompletionSource<bool>();
// When the event returns, set the result, which "completes" the task
service.OnStarted += (o,e) => tcs.TrySetResult(e.Success);
// If an error occurs, error out the task (optional)
service.OnStartError += (o,e) => tcs.TrySetException(e.Exception);
// Start the service call
service.Start();
// Return the Task<T>
return tcs.Task;
}
Task StartAsync()
{
var tcs=new TaskCompletionSource();
//当事件返回时,设置“完成”任务的结果
service.onstart+=(o,e)=>tcs.TrySetResult(e.Success);
//如果发生错误,请将任务出错(可选)
service.OnStartError+=(o,e)=>tcs.TrySetException(e.Exception);
//启动服务呼叫
service.Start();
//返回任务
返回tcs.Task;
}
所以我想我现在明白了这需要怎么做,我现在就是这么做的
服务代码:
public void SetStartTask(Task<bool> startTask)
{
this.startTask = startTask;
}
public bool Start(RtProjectInfo project, string error)
{
StartEventArgs args = new StartEventArgs(project, error);
OnStart(args);
return startTask.Result;
}
protected virtual void OnStart(StartEventArgs e)
{
// thread safe trick, snapshot of event
var se = startEvent;
if (se != null)
{
startEvent(this, e);
}
}
public void StartFinished(MyProject project, string error)
{
OnStartFinish(new StartEventArgs(project, error));
}
protected virtual void OnStartFinish(StartEventArgs e)
{
var sef = startFinished;
if (sef != null)
{
startFinished(this, e);
}
}
public void设置开始任务(任务开始任务)
{
this.startTask=startTask;
}
公共bool启动(RtProjectInfo项目,字符串错误)
{
StartEventArgs args=新的StartEventArgs(项目,错误);
OnStart(args);
返回startTask.Result;
}
受保护的虚拟void OnStart(StartEventArgs e)
{
//线程安全技巧,事件快照
var se=起始事件;
如果(se!=null)
{
startEvent(本,e);
}
}
public void StartFinished(MyProject,字符串错误)
{
OnStartFinish(新的StartEventArgs(项目,错误));
}
开始完成时受保护的虚拟空间(StartEventArgs e)
{
var sef=启动完成;
如果(sef!=null)
{
开始完成(本,e);
}
}
下面是一个测试客户机实现
public void Start_Event(object sender, StartEventArgs e)
{
Task<bool> startTask = StartAsync();
service.SetStartTask(startTask);
DoOtherWork();
DoOtherWork();
DoOtherWork();
}
private Task<bool> StartAsync()
{
var taskCompletion = new TaskCompletionSource<bool>();
service.startFinished += (p, e) =>
{
taskCompletion.TrySetResult((e.Error == string.Empty) ? true : false);
};
return taskCompletion.Task;
}
private void DoingWork()
{
for(int i = 0; i < 100; ++i)
{
}
service.StartFinished(project, error);
}
private void DoOtherWork()
{
for (int i = 0; i < 100000; ++i)
{
}
}
public void Start\u事件(对象发送方,StartEventArgs e)
{
任务startTask=StartAsync();
service.SetStartTask(startTask);
DoOtherWork();
DoOtherWork();
DoOtherWork();
}
专用任务StartAsync()
{
var taskCompletion=new TaskCompletionSource();
service.startFinished+=(p,e)=>
{
taskCompletion.TrySetResult((e.Error==string.Empty)?true:false;
};
返回taskCompletion.Task;
}
私人工作
{
对于(int i=0;i<100;++i)
{
}
服务。启动完成(项目,错误);
}
私人物品
{
对于(int i=0;i<100000;++i)
{
}
}
所以很明显,每当有人客户端调用DoingWork()时,就会收到该事件,并且每个人都很高兴!如果有人有更好的建议,请提供给我,因为我正在学习如何正确使用TPL。上面的代码是否在App.exe端用于此场景?不管怎样,我刚刚意识到(或者我想我是这样做的)应该在哪里:)我将编辑我的代码,以便您可以看到我正在尝试做什么,对于如何使用TaskCompletionSource,我仍然有点困惑。这取决于具体情况,但在实现此模式时,在任务完成后删除处理程序非常重要。至少,如果事件曾多次触发,或者触发事件的对象将比此方法长一段时间。@Servy如何在这样的模式中删除处理程序?
public void Start_Event(object sender, StartEventArgs e)
{
Task<bool> startTask = StartAsync();
service.SetStartTask(startTask);
DoOtherWork();
DoOtherWork();
DoOtherWork();
}
private Task<bool> StartAsync()
{
var taskCompletion = new TaskCompletionSource<bool>();
service.startFinished += (p, e) =>
{
taskCompletion.TrySetResult((e.Error == string.Empty) ? true : false);
};
return taskCompletion.Task;
}
private void DoingWork()
{
for(int i = 0; i < 100; ++i)
{
}
service.StartFinished(project, error);
}
private void DoOtherWork()
{
for (int i = 0; i < 100000; ++i)
{
}
}