2017-01-09 4 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

私は間違っているかもしれませんので、私の論理に従ってください:['Task。Run'](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/task-wait-and-inlining /))。それ以外は、スレッドプール上で実行されます。 – Douglas

答えて

1

@Nicoが理想的という点で正しいです、あなたは非同期プログラミングのすべての方法を使用することができます。この方法は、スリープ状態のスレッドを無駄にしない(またはより現実的な例では、I/Oをブロックする)ため、理想的です。

タスクがメインスレッド以外のスレッドで実行されていることを確認できますか?

はい。 Task.Runは常にスレッドプールに作業をキューイングし、メイン(エントリポイント)スレッドは決してスレッドプールスレッドではありません。

10

私は、あなたが試みていることを達成するためのさまざまな方法があると思います。しかし、あなたがしようとしていることに基づいて、私はasync/awaitを使用するだけで、あなたのUIを確実にブロックすることはなく、タスクを非同期的に制御することができます。 MSDNとして

は言う:

非同期メソッドが非ブロック操作であることを意図しています。非同期メソッド内の 式が現在のスレッドをブロックしないようにするのを待っていますが、待機中のタスクが実行されている間に が実行されています。その代わりに、式は残りのメソッドの を継続として登録し、非同期メソッド の呼び出し元に制御を返します。 asyncキーワードとawaitキーワードでは、追加の スレッドは作成されません。非同期メソッドは独自のスレッドで実行されないため、非同期メソッドはマルチスレッドを必要としません。 メソッドは現在の同期コンテキストで を実行し、メソッドがアクティブな場合にのみスレッド の時刻を使用します。 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; 
} 

このwon'tはあなたのUI

+0

ありがとうございます、しかし、私はTask.Delayを使いたくない、それは質問全体のポイントです。 Thread.Sleepではどのように動作しますか? – thalm

+0

@thalmこの場合、asyncを使用すると、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-task) –

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

関連する問題