7

メソッドからのタスクリターンを使用して、後で使用可能になったときに値を返すようにします。これにより、呼び出し元は、待機を使用してブロックするか、継続をアタッチするか、待機することができます。私が考えることができる最高のものはこれです:

 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は私が探しているものであり、私は自分自身の生活を困難にしているだけですか?

4

3 に答える 3

11

さて、投稿する前にもう少し掘り下げるべきだったと思います。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);
于 2011-05-28T07:23:24.747 に答える
3

WaitHandle.WaitOne()を呼び出すことでスレッドをブロックすることは悪いことですが、それがイベントの仕組みであり、非同期では何も行わないため、選択した回答はあまり意味がありません。

ただし、.NET Frameworkは、スレッドプールのワーカースレッドを利用して、同時に複数のイベントを待機できます(ThreadPool.RegisterWaitForSingleObjec tを参照)。これにより、で複数のWaitHandlesを待機する必要がある場合に、アプリの全体的なリソース使用率が向上します。同時。

したがって、できることは、ワーカースレッドで待機するためのWaitHandleを登録し、必要な継続でコールバックを設定することです。AsyncWaitHandle拡張ライブラリ(NuGet)を使用すると、これを1行で実行できます。

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
}
于 2016-02-22T04:47:49.113 に答える
0

あなたはただTaskEx.WhenAll(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;
}
于 2011-05-27T21:51:05.113 に答える