Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
480 views
in Technique[技术] by (71.8m points)

c# - How to use Task<T> raising an event and waiting for event to be finished

I have the following scenario:

  1. Client who is requesting a webservice to start

    public bool Start(MyProject project, string error)
    
  2. A web service who receives the call from the client in a method

    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;
    }
    
  3. An application that is subscribing to an event that is located in the web service:

    app.Start += EventHandler(App_Start)
    
    private bool App_Start()
    {
       // does something
       returns true/false
    }
    
  4. I want the web service to fire off the event in a Task, then wait for the function in the app.exe to finish and then return here to notify the user that the task has completed successfully.

I am not sure how to do this but in theory it would look something like this:

Task<bool> startTask = Task.Factory.StartNew(() => { OnStart() });
startTask.WaitAll(); // I think this is what I would need to for 4.0
return startTask.Result

I hope I am being descriptive enough for someone to see what I am trying to do. I would like the service to not have to know anything about the client and just run the task and once the event has finished its execution come back to this point and return to client a Boolean value representing success/failure.

Is this possible or am I taking a really wrong approach with this?

Update: Obviously OnStart is not an event so how do I do what you are trying to explain to me?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can wrap an event describing the Event based asynchronous pattern into an Task<T> via TaskCompletionSource<T>. The basic pattern is typically something like:

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;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...