9

.Net 4.5 および ASP MVC 4 RC で Visual Studio 2012 RC を使用しています。非同期を使用するたびにハングします。コントローラー アクション メソッドは非同期を使用しますが、それ自体は非同期コントローラー メソッドではありません。

ログに記録されたエラーやスローされた例外はありませんが、ブラウザには「Waiting for www.myweb.local」と永遠に表示されます。

// Simplest possible async
public class Waiter
{
    public async Task<int> GetValue()
    {
        await Task.Yield();
        return await Task.Factory.StartNew(() => 42);
    }
}

// simplest possible controller that uses the async
public class HomeController : Controller

    public ActionResult Index()
    {
        var waiter = new Waiter();
        var resultTask = waiter.GetValue();
        int result = resultTask.Result;

        // it never gets here 
        return View();
    }
}

この回答に記載されていることを実行しましたが、まだ機能しません。すなわち。web.config には以下が含まれます

<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>

そして魔法の言葉await Task.Yield();は async メソッドにあります。

.Net フレームワークのバージョンは 4.5.50501 です。IIS Express と IIS 6.0 でこの動作を確認しました。

VS2012に「2012年7月更新」を適用してみましたが、直りませんでした。

この答えは、私が待っているときにタスクがすでに完了しているためである可能性があることを示唆していますが、その場合、これは機能するはずですが、機能しません:

public class Waiter
{
    public async Task<int> GetValue()
    {
        await Task.Yield();
        return await Task.Factory.StartNew(() => 
            {
                Thread.Sleep(1500);
                return 42;
            });
    }
}

何人かの人々がそれが必要だと提案しましたConfigureAwait(false)が、このコードも機能しません:

    public async Task<int> GetValue()
    {
        var task = new Task<int>(() => 42);
        return await task.ConfigureAwait(false);
    }

以下、かみそりビュー エンジンでは機能しますが、spark では機能しません。確かに、他のシナリオも機能させる方法があるはずですか? 同期コード内で非同期タスクを使用できないでしょうか?

public class Waiter
{
    public async Task<int> GetValue()
    {
        return await Task.Factory.StartNew(() => 42);
    }
}

public class HomeController : Controller
{
    public async Task<ActionResult> IndexAsync()
    {
        await Task.Yield();
        var waiter = new Waiter();
        int result = await waiter.GetValue();

        return View();
    }
}

これがリリースされたソフトウェアではないことはわかっていますが、Microsoft の RC は通常非常に安定しているため、失敗し、役に立たない方法で失敗することに驚いています。

4

2 に答える 2

11

この質問のように、あなたはデッドロックを引き起こしています。

James Manning の提案は正しいですが、次のようにawaitの結果を得る必要がありますConfigureAwait

public async Task<int> GetValue()
{
    var task = new Task<int> (() => 42);
    return await task.ConfigureAwait(false);
}

一般に、同期コードと非同期コードを混在させることは、自分が何をしているのかを本当に理解していない限り、本当に悪い考えです。コントローラーのアクションを非同期にする方がはるかに優れています。

于 2012-07-06T20:10:53.880 に答える
1

私はベータ版でうまく非同期で動作していました。私はそれをテストしていませんが、コントローラーメソッドが非同期ではないためだと思います。これを次のように変更します。

public async Task<ActionResult> IndexAsync()
{
    var waiter = new Waiter();
    int result = await waiter.GetValue();

    // it never gets here 
    return View();
}
于 2012-07-06T15:41:47.190 に答える