Подтвердить что ты не робот

С# - 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) ответы и комментарии, и мне это уже нравится.
4b9b3361

Ответ 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");
    }
}