English 中文(简体)
有没有一种方法可以使用Task<T>作为未来值T的等待句柄?
原标题:Is there a way to use Task<T> as a waithandle for a future value T?

我想使用方法中的Task return在以后值可用时返回一个值,这样调用方就可以使用Wait来阻止或附加一个continuation,甚至可以等待它。我能想到的最好的方法是:

 public class Future<T> {
    private ManualResetEvent mre = new ManualResetEvent();
    private T value;
    public async Task<T> GetTask() {
        mre.WaitOne();
        return value;
    }
    public void Return(T value) {
        this.value = value;
        mre.Set();
    }
}

主要问题是mre.WaitOne()正在阻塞,所以我假设每次调用GetTask()都会调度一个新线程来阻塞。有没有一种方法可以以异步方式等待WaitHandle,或者已经有一个助手来构建等效的功能?

编辑:好吧,TaskCompletionSource是我想要的吗?我只是在让自己的生活变得艰难吗?

最佳回答

好吧,我想我应该在发布之前多挖一点TaskCompletionSource正是我想要的

var tcs = new TaskCompletionSource<int>();
bool completed = false;
var tc = tcs.Task.ContinueWith(t => completed = t.IsCompleted);
tcs.SetResult(1);
tc.Wait();
Assert.IsTrue(completed);
问题回答

通过调用WaitHandle.WaitOne()阻塞线程是不好的,但这就是事件的工作方式,并且所选的答案没有多大意义,因为它不会异步执行任何操作。

但是,.NET框架可以利用线程池中的工作线程同时等待多个事件(请参阅ThreadPool.RegisterWaitForSingleObject)-如果您需要同时等待多个WaitHandles,这将提高应用程序的总体资源利用率。

So what you can do, is to register the WaitHandle for waiting on a worker thread, and set the callback with desired continuation. With the AsyncWaitHandle extension library (NuGet) this can be done in one line:

var mre = new ManualResetEvent();
T myValue = ...;
Task<T> futureValueTask = mre.WaitOneAsync().ContinueWith(() => myValue);

总的来说,我谦虚的建议是审查代码,然后改为这样做:

async Task MyCode()
{
  var mre = new ManualResetEvent();
  StartDoingSmthAsynchronouslyThatPulsesTheEvent(mre);
  await mre;
  // finish routine here when the event fires
}

难道你不能仅仅利用TaskEx.WenAlll(t1,t2,t3…)来完成等待吗。你需要一个真正的任务来代表工作的完成,但如果你说了这样的话:

private Task<T> myRealWork; 
private T value;
// ...


public async Task<T> GetTask() 
{
    value = await TaskEx.WhenAll(myRealWork); 
    return value;
}

尽管您可能也可以等待myRealWork任务。在您的代码中,我看不出实际计算值的位置。这可能需要以下内容:

public async Task<T> GetTask() 
{
    value = await TaskEx.RunEx(() => ComputeRealValueAndReturnIt()); 
    return value;
}




相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签