C# - ThreadPool QueueUserWorkItem Использовать?

прямо сейчас я использую следующий код для добавления потоков в очереди. Мне это не нравится. И мои коллеги тоже не будут, потому что они не очень хорошо знают C#. Все, что я хочу, это, конечно, очередь метода для выполнения в новом потоке.

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) из ответов и комментарии, и мне это уже больше нравится.

3 ответов


ответ на ваш вопрос зависит от того, как вы проектируете приложение. Вы помещаете его в общий проект ? вы не хотите накладывать расходы на простые операции.

но вы можете создать общий вызов для ThreadPool QueueUserItem, который получает params, 1 param,2 param и т. д.. Это хорошо вместо того, чтобы отправить простую строку и быть ограниченным.

Это, как вы импл параметры QueueUserItem с WaitCallback:

ThreadPool.QueueUserWorkItem(
  new WaitCallback(delegate(object state)
  { YourMethod(Param1, Param2, Param3); }), null);

принято от C# Выполнить метод (с параметрами) с ThreadPool

и некоторые ссылки для ideas:
http://msdn.microsoft.com/en-us/library/4yd16hza.aspx
общий ThreadPool в .NET
разница между делегатами.BeginInvoke и использование потоков ThreadPool в C#


Я не совсем уверен, какой синтаксис вы ищете, но если вам не нравится неиспользованные a в вашем примере, почему бы не использовать ?

Task.Run(() => doStuff("hello world"));

на самом деле это не кажется намного лучше, но, по крайней мере, у него нет неиспользуемого идентификатора.

Примечание: Task.Run() является .Net 4.5 или более поздней версии. Если вы используете .Net 4, вам нужно сделать:

Task.Factory.StartNew(() => doStuff("hello world"));

что не так коротка.

оба из вышеперечисленных используют пул потоков.

если вы действительно должны избегать использования лямбды, вы можете использовать анонимный делегат (который @nowhewhomustnotbenamed уже упоминался):

Task.Run(delegate { doStuff("Hello, World!"); });

но какой в этом смысл? Это гораздо менее читабельно!


Как насчет этого?

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");
    }
}