1. ホーム
  2. c#

[解決済み] この呼び出しが待機されていないことを警告し、現在のメソッドの実行を継続します。

2022-04-25 19:19:40

質問

VS2012 を手に入れたばかりで、次のことを理解しようとしています。 async .

例えば、ある値をブロックされたソースから取得するメソッドがあるとします。このメソッドの呼び出し元をブロックさせたくはない。値が到着したときに呼び出されるコールバックを取るようにメソッドを書くこともできますが、私はC# 5を使っているので、呼び出し側がコールバックに対処する必要がないように、メソッドを非同期にすることにしました。

// contrived example (edited in response to Servy's comment)
public static Task<string> PromptForStringAsync(string prompt)
{
    return Task.Factory.StartNew(() => {
        Console.Write(prompt);
        return Console.ReadLine();
    });
}

これを呼び出すメソッドの例です。もし PromptForStringAsync が非同期でない場合、このメソッドはコールバックの中にコールバックをネストする必要があります。非同期では、このようにごく自然な方法でメソッドを書くことができるんだ。

public static async Task GetNameAsync()
{
    string firstname = await PromptForStringAsync("Enter your first name: ");
    Console.WriteLine("Welcome {0}.", firstname);

    string lastname = await PromptForStringAsync("Enter your last name: ");
    Console.WriteLine("Name saved as '{0} {1}'.", firstname, lastname);
}

ここまでは順調です。問題は、私が コール GetNameAsyncです。

public static void DoStuff()
{
    GetNameAsync();
    MainWorkOfApplicationIDontWantBlocked();
}

の全体的なポイントは GetNameAsync は、非同期であることです。私は 欲しい なぜなら、私は早急にMainWorkOfApplicationIDontWantBlockedに戻り、GetNameAsyncにバックグラウンドでその事をさせたいからです。しかし、この方法でそれを呼び出すと、コンパイラの警告が GetNameAsync という行があります。

Warning 1   Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

呼び出しが完了する前に現在のメソッドの実行が継続されることは完全に承知しています"。それは ポイント 非同期コードの、ね?

私は自分のコードが警告なしでコンパイルされることを望んでいますが、このコードは私が意図したとおりの動作をしているので、quot;fix" することは何もありません。の戻り値を格納することで、警告を取り除くことができます。 GetNameAsync :

public static void DoStuff()
{
    var result = GetNameAsync(); // supress warning
    MainWorkOfApplicationIDontWantBlocked();
}

しかし、今は余計なコードがある。Visual Studioは、私がこの不要なコードを書かざるを得なかったことを理解しているようで、通常の "value never used" の警告を抑制しています。

GetNameAsyncを非同期でないメソッドでラップすることでも警告を取り除くことができますね。

    public static Task GetNameWrapper()
    {
        return GetNameAsync();
    }

しかし、それすらも もっと 余分なコード だから私は必要のないコードを書くか、不要な警告を許容しなければならないのです。

私のasyncの使い方に何か問題があるのでしょうか?

解決方法は?

もし本当に結果が必要ないのであれば、単に GetNameAsync を返すようにシグネチャを変更しました。 void :

public static async void GetNameAsync()
{
    ...
}

関連する質問に対する回答を見るために検討する。 voidを返すことと、Taskを返すことの違いは何ですか?

更新

その結果が必要な場合は GetNameAsync を返すようにする、といった具合です。 Task<string> :

public static async Task<string> GetNameAsync()
{
    string firstname = await PromptForStringAsync("Enter your first name: ");
    string lastname = await PromptForStringAsync("Enter your last name: ");
    return firstname + lastname;
}

そして、以下のように使用します。

public static void DoStuff()
{
    Task<string> task = GetNameAsync();

    // Set up a continuation BEFORE MainWorkOfApplicationIDontWantBlocked
    Task anotherTask = task.ContinueWith(r => {
            Console.WriteLine(r.Result);
        });

    MainWorkOfApplicationIDontWantBlocked();

    // OR wait for the result AFTER
    string result = task.Result;
}