2015-02-06 14 views
4

我試圖用the following custom task scheduler限制併發Web請求:我使用的是像這樣的TaskScheduler有限的併發塊本身

const int CONCURRENCY_LEVEL = 2; 

static void Main() 
{ 
    TaskFactory factory = new TaskFactory(new LimitedConcurrencyLevelTaskScheduler(CONCURRENCY_LEVEL)); 

    Task.WaitAll(new[] { factory.StartNew(() => SomeAction("first")), factory.StartNew(() => SomeAction("second")) }); 

    Console.WriteLine("All tasks ended");   
    Console.Read(); 
} 

static void SomeAction(string task) 
{ 
    Console.WriteLine(task + " task started"); 
    Console.WriteLine(AnotherTask(task).Result); 
    Console.WriteLine(task + " task ended"); 
} 

static async Task<string> AnotherTask(string task) 
{ 
    return await Task.Run(() => 
    { 
     Console.WriteLine(task + " inner task started"); 
     // imitate web requests 
     Thread.Sleep(200); 
     Console.WriteLine(task + " inner task ended"); 
     return "ok"; 
    }); 
} 

的問題是,內部任務是使用我的LimitedConcurrencyLevelTaskScheduler而不是默認的TaskScheduler。這導致自我閉鎖和輸出是這樣的:

second task started 
first task started 
first inner task started 
second inner task started 
second inner task ended 
first inner task ended 

當我改變CONCURRENCY_LEVEL3或改變factoryTask.Factory那顯然一切正常,其輸出是這樣的:

first task started 
second task started 
first inner task started 
second inner task started 
second inner task ended 
first inner task ended 
ok 
second task ended 
ok 
first task ended 
All tasks ended 

不能更改SomeAction中的代碼。我還可以做些什麼? Microsoft示例中是否存在錯誤?

回答

6

開始從您的自定義任務調度任務時指定TaskCreationOptions.HideScheduler

Task.WaitAll(new[] 
{ 
    factory.StartNew(() => SomeAction("first"), TaskCreationOptions.HideScheduler), 
    factory.StartNew(() => SomeAction("second"), TaskCreationOptions.HideScheduler) 
}); 

MSDN

HideScheduler被看作是當前防止環境調度調度程序在創建的任務中。這意味着在創建的任務中執行的操作(例如StartNewContinueWith)將看到Default作爲當前調度程序。

+0

是的! :)這是我的情況的完美解決方案,非常感謝你:) – Adassko 2015-02-07 14:44:24

2

嘗試

static async Task<string> AnotherTask(string task) 
{ 
    return await Task.Run(() => 
    { 
     Console.WriteLine(task + " inner task started"); 
     // imitate web requests 
     Thread.Sleep(200); 
     Console.WriteLine(task + " inner task ended"); 
     return "ok"; 
    }).ConfigureAwait(false); //<-------- 
} 
+0

是的,它的工作,但正如我所說 - 我不能改變這段代碼。這是一個在真實代碼中的「HttpClient」的內部任務,我沒有可能改變其創建選項 – Adassko 2015-02-06 21:13:39

+0

@Adassko我不明白你的意思!爲什麼你不能'httpclient.GetSomeAsync(...)。ConfigureAwait(false); ' – EZI 2015-02-06 21:16:15

+0

因爲這不是我的一段代碼 - 我只是在調用它。這是從外部插件庫,我希望我的代碼能夠運行任何類型的代碼,而不會阻止 – Adassko 2015-02-06 21:18:51