c# - await 异步方法,其中完成由事件处理程序发出信号

标签 c# .net multithreading asynchronous

我正在使用 Windows Phone 8 中的联系人对象,从异步方法中调用 SearchAysnc。 SearchAsync 要求处理程序订阅 SearchCompleted 事件,并通过其中一个事件参数传递其结果,异步方法需要它来完成其工作(包括调用其他异步方法)。

您如何等待事件的异步完成,即事件模式和异步/等待模式之间的桥梁?

我能想到的唯一解决方案是使用 EventWaitHandle,在等待的任务中等待它,如下所示:

using System.Threading;


async Task<string> MyMethod()
{
    string result = null;
    Contacts cons = new Contacts();
    EventWaitHandle handle = new EventWaitHandle(false,EventResetMode.ManualReset);
    cons.SearchCompleted += (sender,args) =>
    {
        // I do all my work on the results of the contact search in this handler
        result = SomeOtherSynchronousOperation(args.Results);

        // When I'm done, I release the thread which was waiting for the results
        handle.Set();
    };
    cons.SearchAsync(String.Empty, FilterKind.None, "My Contact");

    // I can't block this thread (or can I?)
    // So, I launch a task whose sole job is to wait
    await Task.Run(()=>
    {
       // This gets released by the Contacts.SearchCompleted handler when its work is finished,
       // so that MyMethod can finish up and deliver its result
       handle.WaitOne();
    }

    await DoOtherStuffWithResult(result);

    return result;
}

我的实际解决方案(不完全如上所示)确实有效。虽然上面的代码并不能准确地表示已实现的解决方案(可能是一两个编译问题),但它应该用于表达概念并说明我的问题的要点。

这让我想知道这是否是等待事件处理程序执行的唯一方法,或者接近最佳实践方法的任何地方,如果不是,那么执行此处所需操作的“最佳实践”是什么。

Windows 同步原语在异步/等待世界中是否仍有一席之地?

(根据提供的答案)

这对吗?

using Microsoft.Phone.UserData;

string ExtractWhatIWantFromResults(IEnumerable<Contact> results)
{
    string result;

    // Do my processing on the list of contacts, stuff the results into result

    return string;
}

async Task<string> MyMethod()
{
    Contacts cons = new Contacts();
    TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();

    cons.SearchCompleted += (sender,args) =>
    {
        tcs.TrySetResult(ExtractWhatIWantFromResults(args.Results));
    };
    cons.SearchAsync(String.Empty, FilterKind.None, "My Contact");

    return tcs.Task;
}

最佳答案

TaskCompletionSource 是常用的使用方式。

未测试(不知道如何在不知道您的类/方法的情况下进行测试),

Task<string> MyMethodAsync()
{
    Contacts cons = new Contacts();
    TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();

    cons.SearchCompleted += (sender,args) =>
    {
        tcs.TrySetResult(args.Results);
    };
    cons.SearchAsync(String.Empty, FilterKind.None, "My Contact");

    return tcs.Task;
}

关于c# - await 异步方法,其中完成由事件处理程序发出信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19072602/

相关文章:

Android GridView 和线程等待

c++ - WinAPI 的 sleep 在子线程内不起作用

c# - 添加到列表的并行循环

C#上传视频到Youtube,不提示用户登录: Youtube API V3

c# - Session 和 Cookie 有什么区别?

c# - SqlConnection.CacheConnectionStringProperties().NET 代码中的 NullReferenceException

c# - 这是对 DTO 的正确使用吗?

c# - 带连接的 linq 查询

javascript - .Net Core POST请求数组大小限制

c# - UI线程被阻塞