1. ホーム
  2. c#

[解決済み] Task.Runをメソッドに入れないと非同期にはならないのですか?

2022-03-16 08:35:45

質問

非同期awaitを最もシンプルな形で理解しようとしています。 私はこの例のために2つの数字を足す非常に簡単なメソッドを作りたいのですが、当然のことながら、処理時間は全くありません、ここで例を定式化することが問題なのです。

例1

private async Task DoWork1Async()
{
    int result = 1 + 2;
}

例2

private async Task DoWork2Async()
{
    Task.Run( () =>
    {
        int result = 1 + 2;
    });
}

を待つと DoWork1Async() は、コードが同期的に実行されるのか、それとも非同期的に実行されるのか?

同期コードを Task.Run メソッドを待ち受け可能かつ非同期にすることで、UIスレッドをブロックしないようにするためですか?

私は、自分のメソッドが Task を返すか Task<T> で囲む必要がありますか? Task.Run を使用して非同期にします。

愚かな質問だと思いますが、ネット上では、非同期で、かつ Task.Run または StartNew .

解決方法は?

まず、用語を整理しておきますと、quot;asynchronous" ( async ) は、開始前に呼び出し元のスレッドに制御を戻す可能性があることを意味します。つまり async メソッドでは、これらの "yield"ポイントは await の式で表されます。

これは、MSDNドキュメントで長年使われてきた「バックグラウンドのスレッドで実行される」という意味の(誤った)用語である「asynchronous"」とは全く異なるものです。

さらに問題を混乱させるために async は "awaitable" とは全く異なるもので、いくつかの async メソッドの戻り値の型が待ち受け可能でなく、待ち受け可能な型を返す多くのメソッドが async .

彼らが何をするかはもういい ではない 以下は、その内容です。 :

  • async キーワードは非同期メソッドを可能にします(つまり、このキーワードで await の式)。 async メソッドは Task , Task<T> または、(どうしても必要な場合は) void .
  • あるパターンに従った型はすべてawaitableにすることができます。最も一般的な待ち受け可能な型は TaskTask<T> .

では、質問を「どのようにオペレーションを実行すればよいのでしょうか? バックグラウンドのスレッドで を待ち受けることができるようにすることです。 Task.Run :

private Task<int> DoWorkAsync() // No async because the method does not need await
{
  return Task.Run(() =>
  {
    return 1 + 2;
  });
}

(しかし、このパターンは貧しいアプローチです。)

しかし、あなたの質問が、「どのようにして async メソッドをブロックする代わりに呼び出し元に返すことができます。 async を使用し await は、そのquot;yielding"ポイントに使用されます。

private async Task<int> GetWebPageHtmlSizeAsync()
{
  var client = new HttpClient();
  var html = await client.GetAsync("http://www.example.com/");
  return html.Length;
}

つまり、物事の基本的なパターンとしては async の中でquot;awaitables"に依存するコードです。 await の式で表されます。これらの"awaitables"は、他の async メソッド、あるいは単に待ち行列を返す通常のメソッドです。通常のメソッドは Task / Task<T> 使用 Task.Run を使用してバックグラウンドスレッドでコードを実行することもできますし、(より一般的な方法として)バックグランドスレッドで TaskCompletionSource<T> またはそのショートカットの1つ ( TaskFactory.FromAsync , Task.FromResult など)。I しない でメソッド全体を包むことをお勧めします。 Task.Run 同期メソッドは同期シグネチャを持つべきであり、それを Task.Run :

private int DoWork()
{
  return 1 + 2;
}

private void MoreSynchronousProcessing()
{
  // Execute it directly (synchronously), since we are also a synchronous method.
  var result = DoWork();
  ...
}

private async Task DoVariousThingsFromTheUIThreadAsync()
{
  // I have a bunch of async work to do, and I am executed on the UI thread.
  var result = await Task.Run(() => DoWork());
  ...
}

私は async / await イントロ を私のブログで紹介しました。最後に、良いフォローアップのリソースをいくつか紹介します。のMSDNドキュメントは async も珍しく良いですね。