1

WebAPI ASP.NET ソリューションがあります。私はweb.configを次のように設定しました:

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

呼び出しでは、3 つのタスク (それぞれ 10 秒) の結果を取得する必要があります。

 Task<Cat> catAsync = GetCatAsync();
 Task<Dog> dogAsync = GetDogAsync();
 Task<Pig> pigAsync = GetPigAsync();

 await Task.WhenAll(catAsync , dogAsync , pigAsync );

 cat= catAsync.Result;
 dog= dogAsync.Result;
 pig= pigAsync.Result;

私はそれを一度呼び出すことができますが、これへの後続の呼び出しはスレッドで終了するように見えます.CatとDogは実行されるかもしれませんが、Pigは気化するようです. 1 分ほど後に、これらが表示され始めます。

The thread '<No Name>' (0x2f60) has exited with code 0 (0x0).
The thread '<No Name>' (0x974) has exited with code 0 (0x0).
The thread '<No Name>' (0x1ea8) has exited with code 0 (0x0).

私のタスクは次のようになります。

    private async Task<Cat> CatAsync()
    {
        await Task.Run(() =>
            {
               //Use WCF to get some data from a service
            });

        return cat;
    }

IISRESET を実行すると、もう一度サイトを実行できます。

*編集

Panagiotis Kanavos による回答を読んだ後、この例で動作する以下のソリューションを投稿しました

4

5 に答える 5

4

他の人が示唆する問題は、同期コンテキストです。Await は、待機を開始した同期コンテキスト (基本的にはスレッド) で実行を再開します。そのスレッドがすでにブロックされている場合。他の何かを待つことによって、コードはデッドロックします。

これを回避するには、 への呼び出しの後に へawaitの呼び出しをConfigureAwait(false)続けて、ランタイムを別のスレッドで継続させる必要があります。

次のコードはスムーズに実行されます。ただし、ConfigureAwait 呼び出しを削除すると、デッドロックが発生します。

さらに、xxxAsync メソッドを使用する限り、Task.Run 内で WCF 呼び出しを行う必要はありません。これにより、コードも非常にきれいになります

最後に、完了を待つだけの場合は、await Task.WhenAll() の代わりに Task.WaitAll() を使用する必要があります。Task.WaitAll() は同期コンテキストを混乱させないため、別の ConfigureAwait() を追加する必要はありません

protected void Page_Load(object sender, EventArgs e)
    {
        var results = GetThem().Result;

    }

    private async Task<Tuple<Cat,Dog,Pig>> GetThem()
    {
        Task<Cat> catAsync = GetCatAsync();
        Task<Dog> dogAsync = GetDogAsync();
        Task<Pig> pigAsync = GetPigAsync();

        await Task.WhenAll(catAsync, dogAsync, pigAsync).ConfigureAwait(false);
        //better yet,
        //   Task.WaitAll(catAsync, dogAsync, pigAsync);

        var cat = catAsync.Result;
        var dog = dogAsync.Result;
        var pig = pigAsync.Result;
        return Tuple.Create(cat, dog, pig);
    }

    private async Task<Pig> GetPigAsync()
    {
        var cat = new Pig();
        var res = await GetGoogleSearchHTML("cat").ConfigureAwait(false);
        using (StreamReader sr = new StreamReader(res.GetResponseStream()))
        {
            cat.Name = await sr.ReadToEndAsync().ConfigureAwait(false);
        }

        return cat;
    }

    public async Task<WebResponse> GetGoogleSearchHTML(string type)
    {
        System.Net.WebRequest request = System.Net.HttpWebRequest.Create(String.Format("http://www.google.com/search?noj=1&site=cat&source=hp&q={0}&oq=search", type));
        System.Net.WebResponse response = await request.GetResponseAsync().ConfigureAwait(false);
        return response;
    }
于 2013-06-20T11:59:55.597 に答える
1

@Panagiotis Kanavosの答えはそれを機能させました。これは、Google 社員のために Web API を使用して IIS でタスクを動作させる方法の簡潔な要約です。

Web.Config に追加

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

次に、タスクを作成し、WaitAll() を使用します

 Task<Cat> cat= GetCat();
 Task<Dog> dog= GetDog();     
 Task.WaitAll(cat,dog,pig etc);

 NowUseTheValues(cat.Result,dog.Result);

タスクは、非同期のない単純なタスクである必要があります。

 private  Task<Cat> GetCat()
 {
     return Task.Run(() => {
            return new Cat();
       });
 }
于 2013-06-20T16:15:54.680 に答える
0

関数から async-await を削除してみてください。

private Task<Cat> CatAsync()
{
    return Task.Run(() =>
        {
           //Use WCF to get some data from a service
        });
}

外部関数で await を保持できます。説明については、これを確認してください:この非同期アクションがハングするのはなぜですか?

于 2013-06-19T23:17:57.310 に答える
-1

コム、

あなたのコードで動作するようになりました (WebRequest と Web Response を使用 - WCF 呼び出しで同期)

WebResponse/Requests Async (WCF 呼び出しを行う場所) の 1 つを作成するとすぐに、ハングしました。

 private async Task<Cat> GetCatAsync()
        {
            Cat cat = new Cat(); ;
            await Task.Run(() =>
            {
                //Use WCF to get some data from a service
                var res = GetGoogleSearchHTML("cat").Result;
                using (StreamReader sr = new StreamReader(res.GetResponseStream()))
                {
                    cat.catName = sr.ReadToEnd();
                }
            });

            return cat;
        }

        public async Task<WebResponse> GetGoogleSearchHTML(string type)
        {
            System.Net.WebRequest request = System.Net.HttpWebRequest.Create(String.Format("http://www.google.com/search?noj=1&site=cat&source=hp&q={0}&oq=search",type));
            System.Net.WebResponse response = await request.GetResponseAsync();
            return response;
        }

        public class Dog {
            public string dogName { get; set; }
            }


        public class Pig
        {
            public string pigName { get; set; }
        }


        public class Cat
        {
            public string catName { get; set; }
        }


        private async Task<Dog> GetDogAsync()
        {
            Dog dog = new Dog(); 

            await Task.Run(() =>
            {
                WebResponse res = GetGoogleSearchHTML("dog").Result;
                using (StreamReader sr = new StreamReader(res.GetResponseStream()))
                {
                    dog.dogName = sr.ReadToEnd();
                }
                //Use WCF to get some data from a service
            });

            return dog;
        }

        private async Task<Pig> GetPigAsync()
        {
            Pig pig = new Pig(); ;

            await Task.Run(() =>
            {
                var res = GetGoogleSearchHTML("pig").Result;
                using(StreamReader sr = new StreamReader(res.GetResponseStream()))
                {
                    pig.pigName = sr.ReadToEnd();
                }
                //Use WCF to get some data from a service
            });

            return pig;
        }

        public async void GetTypes()
        {
         List<Task> taskList = new List<Task>() {  };


             Task<Cat> catAsync = GetCatAsync();
             Task<Dog> dogAsync = GetDogAsync();
             Task<Pig> pigAsync = GetPigAsync();

         await Task.WhenAll(catAsync , dogAsync , pigAsync );

        var cat= catAsync.Result;
        var dog= dogAsync.Result;
        var pig= pigAsync.Result;
        }



public WebApiResult GetResponses()
{

GetTypes();

return new WebApiResult();

}
于 2013-06-20T01:02:32.517 に答える