С# - ThreadPool QueueUserWorkItem Использовать?
Только сейчас я использую следующий код для добавления потоков в очередь. Мне это не нравится. И мои коллеги не будут, потому что они не очень хорошо знают С#. Все, что я хочу, это, конечно, очередь на метод, который будет выполняться в новом потоке.
private static void doStuff(string parameter)
{
// does stuff
}
// call (a)
ThreadPool.QueueUserWorkItem(a => doStuff("hello world"));
// call (b)
ThreadPool.QueueUserWorkItem(delegate { doStuff("hello world"); });
Также существуют другие варианты использования ThreadPool.QueueUserWorkItem
?
Лучшим будет другой 1-Line-Call. Если возможно, используйте Func<>
или Action<>
.
EDIT: Получите (b) ответы и комментарии, и мне это уже нравится.
Ответы
Ответ 1
Ответ на ваш вопрос зависит от того, как вы разрабатываете приложение. Вы вкладываете его в общий проект? вы не хотите навязывать простые операции.
Но вы могли бы создать общий вызов для ThreadPool QueueUserItem, который получает параметры, 1 param, 2 param и т.д. Это хорошо, а не отправлять простую строку и быть ограниченным.
Это, как вы ввели параметры QueueUserItem с WaitCallback:
ThreadPool.QueueUserWorkItem(
new WaitCallback(delegate(object state)
{ YourMethod(Param1, Param2, Param3); }), null);
взято из С# Execute Method (с параметрами) с ThreadPool
И некоторые ссылки на идеи:
http://msdn.microsoft.com/en-us/library/4yd16hza.aspx
Общий ThreadPool в .NET
Разница между делегатом .BeginInvoke и использованием потоков ThreadPool на С#
Ответ 2
Я не совсем уверен, какой синтаксис вы ищете, но если вам не нравится неиспользованный a
в вашем примере, почему бы не использовать Task
вместо этого?
Task.Run(() => doStuff("hello world"));
На самом деле это не выглядит намного лучше, но по крайней мере у него нет неиспользуемого идентификатора.
Примечание: Task.Run()
-.Net 4.5 или новее. Если вы используете .Net 4, вам нужно сделать:
Task.Factory.StartNew(() => doStuff("hello world"));
который не так короток.
Оба из вышеперечисленных используют пул потоков.
Если вам действительно нужно избегать использования лямбда, вы можете использовать анонимный делегат (который уже не упоминается):
Task.Run(delegate { doStuff("Hello, World!"); });
Но в чем смысл этого? Это гораздо менее читаемо!
Ответ 3
Как насчет этого?
class Program
{
static void Main(string[] args)
{
ThreadPool.QueueUserWorkItem(MyWork, "text");
Console.ReadKey();
}
private static void MyWork(object argument)
{
Console.WriteLine("Argument: " + argument);
}
}
Или, если вы не хотите быть ограничивающим подпись и имеете простой способ поместить методы в поток, вы можете сделать это так. Для методов, которые делают и не возвращают значение и могут иметь до 6 параметров, это потребует вы должны определить 12 перегрузок, если я не ошибаюсь. Это требует немного больше работы спереди, но более прост в использовании.
class Program
{
static void Main(string[] args)
{
var myClass = new MyClass();
myClass.DoWork();
Console.ReadKey();
}
}
public static class ObjectThreadExtension
{
public static void OnThread(this object @object, Action action)
{
ThreadPool.QueueUserWorkItem(state =>
{
action();
});
}
public static void OnThread<T>(this object @object, Action<T> action, T argument)
{
ThreadPool.QueueUserWorkItem(state =>
{
action(argument);
});
}
}
public class MyClass
{
private void MyMethod()
{
Console.WriteLine("I could have been put on a thread if you like.");
}
private void MySecondMethod(string argument)
{
Console.WriteLine(argument);
}
public void DoWork()
{
this.OnThread(MyMethod);
this.OnThread(MySecondMethod, "My argument");
}
}