6

私が試した次のコードのすべてのバリエーションは機能しDoSomething() : voidませDoSomething() : Taskん。表示されるエラーには、 、、およびが含まれます。TaskEx.RunEx().GetAwaiter().GetResult()"Start may not be called on a task with null action""RunSynchronously may not be called on a task unbound to a delegate""The task has not yet completed"

class Program
{
    static void Main(string[] args) // Starting from a non-async method
    {
        DoSomething();

        Console.WriteLine("Press any key to quit.");
        Console.ReadKey();
    }

    static async void DoSomething()
    {
        Console.WriteLine("Starting DoSomething ...");

        var x = await PrepareAwaitable(1);

        Console.WriteLine("::" + x);

        var y = await PrepareAwaitable(2);

        Console.WriteLine("::" + y);
    }

    static Task<string> PrepareAwaitable(int id)
    {
        return new Task<string>(() =>
        {
            return "Howdy " + id.ToString();
        });
    }
}

出力:

DoSomething を開始しています...

終了するには、任意のキーを押します。

PrepareAwaitableのは後でより複雑になりますTaskActionこのアクションが完了すると、時間がかかりますが、 (または他のフレームワークメカニズム)が x に割り当てられ、その後 y にTask割り当てられることによって再開されると思います。"Howdy ..."私が本当にやりたいことは、待機中のオブジェクトをインターセプトし、それらを処理し、後で制御して、結果 ( xand y) で継続を再開することです。しかし、私はその大きな一歩を踏み出すことができなかったので、小さな一歩から始めようとしています.

4

4 に答える 4

11

まず、タスクベースの非同期パターンのドキュメントを読んでください。の下My Documents\Microsoft Visual Studio Async CTP\Documentationです。このドキュメントでは、 で自然に使用できる API を設計する方法について説明しますawait

次に、Task新しい非同期の世界では実際には適用されなくなった、クラスおよび関連する API のいくつかの側面があることを認識してください。Taskはもともと TPL の中核として書かれました。非同期プログラミングに適していることが判明したため、Microsoft は新しい "Promise" クラスを作成する代わりにそれを使用しました。ただし、多くのメソッドはホールドオーバーであり、TPL で使用されますが、非同期プログラミングには必要ありません。

タイトルの質問に答えるために、同期コードと非同期コードを混在させることは、現在の非同期 CTP では簡単ではありません。拡張メソッドを含むライブラリを作成しましたTask.WaitAndUnwrapException。これにより、同期コードから非同期コードを簡単に呼び出すことができます。「任意のキーを押す」というプロンプトが不要になるmy AsyncContextclassにも興味があるかもしれません。

于 2011-12-09T01:12:44.260 に答える
5

非同期処理は何も行われていないため、何を達成しようとしているのかは明確ではありません。たとえば、これはコンパイルして実行しますが、それがあなたが望むものかどうかわかりません:

using System;
using System.Threading.Tasks;

class Program
{
    static void Main(string[] args)
    {
        DoSomething();

        Console.WriteLine("Press any key to quit.");
        Console.ReadKey();
    }

    static async void DoSomething()
    {
        Console.WriteLine("Starting DoSomething ...");

        var x = await PrepareAwaitable(1);

        Console.WriteLine("::" + x);

        var y = await PrepareAwaitable(2);

        Console.WriteLine("::" + y);
    }

    static async Task<string> PrepareAwaitable(int x)
    {
        return "Howdy " + x;
    }
}

PrepareAwaitable非同期のものは何もないため、これは警告を発することに注意してください。「待機」表現はありません。プログラム全体が同期的に実行されます。の別の代替実装PrepareAwaitable:

static Task<string> PrepareAwaitable(int x)
{
    return TaskEx.Run(() => "Howdy " + x);
}

それはあなたが求めていたものに似ていますか?

于 2011-12-08T23:03:15.853 に答える
5

返されたタスクはまだ開始されていません (つまり、「コールド」タスクです)。PrepareAwaitable コードを次のように置き換えてみてください。

static Task<string> PrepareAwaitable(int x)
{
    return Task.Factory.StartNew<string>(() =>
    {
        return "Howdy " + x.ToString();
    });
}
于 2011-12-08T23:03:57.750 に答える