2017-01-09 54 views
2

是否有可能確保任務在主線程以外的另一個線程上運行?所以這段代碼不會調用調用線程?如何使用Thread.Sleep與Task.Run沒有阻止主胎面

var task = Task.Run(() => 
{ 
    //third party code i don't have access to 
    Thread.Sleep(3000); 
}); 

我知道有Task.Delay但我想,以確保該任務將在另一個線程上運行。

+1

我可能錯了,所以按照我的邏輯:['任務。運行'](https://msdn.microsoft.com/en-us/library/system.threading.tasks.task.run(v = vs.110).aspx)「排隊指定的工作在ThreadPool上運行」 ,我*假設*這是[管理線程池](https://msdn.microsoft.com/en-us/library/0ka9477y(v = vs.110).aspx),它表示:「線程池線程是後臺線程「。因此,所有的'Task.Run'調用都會在後臺線程上產生線程。我假設'Main'線程始終是一個前臺線程,如果是'Task.Run'永遠不會在主線程上。用'Thread.CurrentThread.IsBackground'檢查。 – Quantic

+0

感謝您的信息,我會對此進行調查。我假設任務可能會或可能不會在另一個線程上運行,具體取決於任務調度程序認爲是正確的。所以我正在尋找一個是確保它是另一個線程。但如果你是對的,那麼情況總是如此。 – thalm

+1

它可以在主線程上運行的唯一方法是,如果您在主線程開始執行之前等待它(通過[任務內聯](https://blogs.msdn.microsoft.com/pfxteam/2009/10)/15 /任務等待和內聯/))。除此之外,它將在線程池中執行。 – Douglas

回答

1

@Nico是在正確的理想情況下,你可以使用異步編程的所有道路。這種方法非常理想,因爲它不會浪費睡眠線程(或者更實際的例子是阻塞I/O)。

是否有可能確保任務在主線程之外的另一個線程上運行?

是的。 Task.Run將始終將工作排隊到線程池,並且主(入口點)線程永遠不會是線程池線程。

10

我認爲有不同的方法來完成你正在嘗試。但是基於你正在嘗試做的事情,我認爲你只需使用async/await就可以了,這不會妨礙你的用戶界面,並且允許你異步地控制你的任務。

由於MSDN說:

異步方法旨在爲非阻塞操作。在異步方法中等待 表達式不會阻塞當前線程,而 等待執行的任務正在運行。相反,該表達式將該方法的其餘 作爲延續並將控制返回給異步方法的調用者 。異步和等待關鍵字不會導致創建其他 線程。異步方法不需要多線程 ,因爲異步方法不會在其自己的線程上運行。該方法在當前同步上下文上運行 ,並僅在該方法處於活動狀態時纔在線程 上使用時間。您可以使用Task.Run將CPU綁定的 工作移動到後臺線程,但後臺線程不會幫助 一個只等待結果可用的進程。

https://msdn.microsoft.com/en-us/library/mt674882.aspx

這是使用的例子:

public async Task MyMethodAsync() 
{ 
    Task<int> runTask = RunOperationAsync(); 

    int result = await longRunningTask; 

    Console.WriteLine(result); 
} 

public async Task<int> RunOperationAsync() 
{ 
    await Task.Delay(1000); //1 seconds delay 
    return 1; 
} 

這不會致使阻止你的UI

+0

感謝,例如,但我不想使用Task.Delay,這是整個問題的關鍵。它如何與Thread.Sleep一起工作? – thalm

+0

@thalm在這種情況下使用async/await Task.Delay具有與Thread.Sleep相同的用法,但不會阻止您的主線程。看看這個Jon Skeet的答案http://stackoverflow.com/a/13430126/637840 – NicoRiff

+0

問題是,Thread.Sleep是在用戶生成的代碼,我沒有訪問。我不能改變它Task.Delay ... – thalm

-2

您當前的代碼應該工作,但是你將需要調用Start()方法調用它的任務。

您也可以通過線程實現這一點:

new System.Threading.Thread(() => { 
    System.Threading.Thread.Sleep(500); 
}).Start(); 
+3

應儘可能避免創建線程,因爲重複使用已經創建的線程比創建新線程更便宜。看看[爲什麼線程和任務之間性能差異如此之大?](http://stackoverflow.com/questions/13125105/why-so-much-difference-in-performance-between-thread-and-任務) –

0

使用線程池。

static void Main(string[] args) 
    { 
     ThreadPool.QueueUserWorkItem(o => { Thread.Sleep(5000); Console.WriteLine("Threadpool task done."); }); 
     for(int i = 0; i < 10; i++) 
     { 
      Console.WriteLine("Main thread: {0}", i); 
      Thread.Sleep(1000); 
     } 

     Console.ReadLine(); 
    } 

輸出應該是這樣的: enter image description here