我有以下情况:
请求启动网络服务的客户
public bool Start(MyProject project, string error)
通过方法
接收来自客户端的呼叫的Web服务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;
}
订阅位于Web服务中的事件的应用程序:
app.Start += EventHandler(App_Start)
private bool App_Start()
{
// does something
returns true/false
}
我希望Web服务在任务中触发事件,然后等待app.exe中的函数完成,然后返回此处以通知用户该任务已成功完成。
我不知道该怎么做但理论上它看起来像这样:
Task<bool> startTask = Task.Factory.StartNew(() => { OnStart() });
startTask.WaitAll(); // I think this is what I would need to for 4.0
return startTask.Result
我希望我的描述能够让某人看到我想要做的事情。我希望服务不必了解客户端,只需运行任务,一旦事件完成执行,就会返回到客户端,返回一个表示成功/失败的布尔值。
这是可能的还是我采取了一种非常错误的做法?
更新 显然OnStart不是一个事件,所以我该怎么做你要向我解释的内容?
答案 0 :(得分:2)
您可以通过TaskCompletionSource<T>
将描述基于事件的异步模式的事件包装到Task<T>
中。基本模式通常类似于:
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;
}
答案 1 :(得分:1)
所以我想我现在明白这里需要做的是我现在是怎么做的。
服务代码:
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 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)
{
}
}
很明显,每当有人打电话给DoingWork()时,都会收到活动,大家都很开心!如果有人有任何更好的建议请提供,因为我正在学习如何正确使用TPL。