在C# 如果我有一个函数接受 callback,可以用 Task 来阻止回调扩散吗?

假设我已经实现了这样的函数:

delegate Result ResponseDelegate(object identifier);

void AddCallback(object identifier, ResponseDelegate callback);

现在我希望通过一种同步式的接口来获取结果(阻止回调式的代码扩散),可以用 Task 或者其他库来做到吗?

具体来说就是,通过实现一个

Task<Result> GetResult(object identifier);

或者其他近似形式的方法(不带有回调)来获取 Result 是有可能的吗?

阅读 5k
1 个回答

按照类型来看,你要的不就是这个构造函数吗(https://msdn.microsoft.com/en-us/library/dd321458(v=vs.110).aspx)?

我总有一种你的ResponseDelegate的参数和返回值类型颠倒了的感觉,如果不对的话,你的内部结构反正也得有典型的异步函数的特征。在这里我给你介绍一下 TaskCompleteSource 类:

// 假设你有标准的async行为的旧函数
IAsyncResult BeginDoSomething(object identifier, Action<IAsyncResult> callback);
Result EndDoSomething(IAsyncResult asyncResult);

Task<Result> DoSomethingAsync(object identifier)
{
    var t = new TaskCompleteSource<Result>();
    BeginDoSomething(identifier, r=>
    {
        t.TrySetResult(EndDoSomething(r));
    });
    return t.Task;
}

如果你的意思是说,你AddCallback之后,这个函数就会被随便找一个线程(譬如QueueUserWorkItem)来执行,然后你可以通过GetResult来获取那个Task。那么你大概可以这么做:

Dictionary<object, Task<Result>> tasks = {};

void AddCallback(object identifier, Func<object, Result> callback)
{
    var t = new TaskCompleteSource<Result>();
    tasks.Add(identifier, t.Task);
    
    ThreadPool.QueueUserWorkItem(id=>
    {
        t.TrySetResult(callback(id));
    }, identifier);
}

Task<Result> GetResult(object identifier)
{
    return tasks[identifier];
}
logo
Microsoft
子站问答
访问
宣传栏