次のようなコードは、新しいスレッドを開始してジョブを実行します。そのスレッドの優先度を制御する方法はありますか?
Task.Factory.StartNew(() => {
// everything here will be executed in a new thread.
// I want to set the priority of this thread to BelowNormal
});
これは、スレッドプールを使用するかどうかを決定するときに「しない」ことの1つです;-)
詳細はこちら: http://msdn.Microsoft.com/en-us/library/0ka9477y.aspx
そのため、答えは「いいえ、Theadsプールで作成されたスレッドに特定の優先順位を指定することはできません」です。
一般的なスレッディングの時点で、 Thread.Priority propertyについて既に知っているに違いない
他の人が述べたように、タスクに合わせてカスタムスケジューラを指定する必要があります。残念ながら、適切な組み込みスケジューラはありません。
GlennがリンクしたParallelExtensionsExtrasを使用することもできますが、コードに直接貼り付けることができる単純なものが必要な場合は、次を試してください。次のように使用します。
Task.Factory.StartNew(() => {
// everything here will be executed in a thread whose priority is BelowNormal
}, null, TaskCreationOptions.None, PriorityScheduler.BelowNormal);
コード:
public class PriorityScheduler : TaskScheduler
{
public static PriorityScheduler AboveNormal = new PriorityScheduler(ThreadPriority.AboveNormal);
public static PriorityScheduler BelowNormal = new PriorityScheduler(ThreadPriority.BelowNormal);
public static PriorityScheduler Lowest = new PriorityScheduler(ThreadPriority.Lowest);
private BlockingCollection<Task> _tasks = new BlockingCollection<Task>();
private Thread[] _threads;
private ThreadPriority _priority;
private readonly int _maximumConcurrencyLevel = Math.Max(1, Environment.ProcessorCount);
public PriorityScheduler(ThreadPriority priority)
{
_priority = priority;
}
public override int MaximumConcurrencyLevel
{
get { return _maximumConcurrencyLevel; }
}
protected override IEnumerable<Task> GetScheduledTasks()
{
return _tasks;
}
protected override void QueueTask(Task task)
{
_tasks.Add(task);
if (_threads == null)
{
_threads = new Thread[_maximumConcurrencyLevel];
for (int i = 0; i < _threads.Length; i++)
{
int local = i;
_threads[i] = new Thread(() =>
{
foreach (Task t in _tasks.GetConsumingEnumerable())
base.TryExecuteTask(t);
});
_threads[i].Name = string.Format("PriorityScheduler: ", i);
_threads[i].Priority = _priority;
_threads[i].IsBackground = true;
_threads[i].Start();
}
}
}
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{
return false; // we might not want to execute task that should schedule as high or low priority inline
}
}
ノート:
MaximumConcurrencyLevel
、GetScheduledTasks
、およびTryExecuteTaskInline
に対するBnayaの選択に従ってください。タスクのスレッド優先度は、タスクを実行する実際のメソッド内で設定できます。ただし、問題を回避するために完了したら、優先度を元に戻すことを忘れないでください。
そのため、最初にタスクを開始します。
new TaskFactory().StartNew(StartTaskMethod);
次に、スレッドの優先度を設定します。
void StartTaskMethod()
{
try
{
// Change the thread priority to the one required.
Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
// Execute the task logic.
DoSomething();
}
finally
{
// Restore the thread default priority.
Thread.CurrentThread.Priority = ThreadPriority.Normal;
}
}
優先度を変更するときは、次のことに注意してください。 なぜThreadPool(またはTask)スレッドの優先度を変更しないのですか?
Task
で優先度を設定するには、Microsoftの専門家によって記述されたカスタムタスクスケジューラを確認してください Stephen Toub inこのMSDNブログ投稿 =。詳細については、彼が最初の文で言及した前の2つの投稿へのリンクをお見逃しなく。
あなたの問題については、QueuedTaskScheduler
を見たくなるかもしれません。