2013-07-02 18 views
19

Właśnie teraz używam następującego kodu, aby dodać kolejki wątków. Nie podoba mi się to. I moi koledzy też tego nie zrobią, ponieważ nie znają dobrze C#. Wszystko, czego chcę, to oczywiście kolejkowanie metody do wykonania w nowym wątku.C# - ThreadPool QueueUserWorkItem Use?

private static void doStuff(string parameter) 
{ 
    // does stuff 
} 

// call (a) 
ThreadPool.QueueUserWorkItem(a => doStuff("hello world")); 
// call (b) 
ThreadPool.QueueUserWorkItem(delegate { doStuff("hello world"); }); 

więc istnieją inne odmiany użytkowe ThreadPool.QueueUserWorkItem?

Najlepsze byłoby kolejne 1-liniowe połączenie. Jeśli to możliwe, użyj Func<> lub Action<>.


EDYCJA: Dostałem (b) z odpowiedzi i komentarzy i już mi się podoba.

+2

Co jest nie tak z ThreadPool.QueueUserWorkItem() w twoim scenariuszu? –

+1

można użyć słowa kluczowego "delegate". Coś jak, ThreadPool.QueueUserWorkItem (delegate {doStuff ("");}). Tak jak powyższa metoda, ale jak chcesz, jest to po prostu inny sposób robienia tego .. –

+1

Dlaczego na świecie uważasz, że składnia delegatów jest czystsza niż lambdy !? –

Odpowiedz

12

Odpowiedź na pytanie zależy od sposobu zaprojektowania aplikacji. Czy umieścisz to we wspólnym projekcie? nie chcesz napowietrzać prostych operacji.

Ale można utworzyć ogólne wywołanie ThreadPool QueueUserItem, które odbiera params, 1 parametr, 2 parametry, itd. To jest dobre zamiast wysyłania prostego łańcucha i jest ograniczone.

To jak IMPL do parametrów QueueUserItem z WaitCallback:

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

zaczerpnięte z C# Execute Method (with Parameters) with ThreadPool

A niektóre linki do pomysłów:
http://msdn.microsoft.com/en-us/library/4yd16hza.aspx
Generic ThreadPool in .NET
Difference between delegate.BeginInvoke and using ThreadPool threads in C#

+0

Czy byłoby to również możliwe w przypadku 'Func' lub' Action' lub bez dodatkowej treści wywołania? – Bitterblue

+0

Będzie to możliwe, gdy zbudujesz WaitCallback, nie wysyłaj zwykłego "delegata", zamiast tego wyślij własnego delegata. * ale *, jak spodziewasz się odzyskać wynik? zazwyczaj podczas wysyłania operacji do wątku roboczego nie oczekujesz rezultatu, tylko upewniając się, że zadanie zostało wykonane. Możesz to osiągnąć poprzez implementację wzorca asynchronicznego. http://www.c-sharpcorner.com/UploadFile/rmcochran/multithreadasyncwebservice05262007094719AM/multithreadasyncwebservice.aspx – ilansch

13

Nie jestem do końca pewien, jakiego rodzaju składni szukasz, ale jeśli nie podoba ci się nieużywany a w twoim przykładzie, dlaczego zamiast tego użyć Task?

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

To naprawdę nie wydaje się dużo lepsze, ale przynajmniej nie ma niewykorzystanego identyfikatora.

Uwaga: Task.Run() to .Net 4.5 lub nowszy. Jeśli używasz .Net 4, musisz zrobić:

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

który nie jest tak krótki.

Oba powyższe elementy wykorzystują pulę wątków.

Jeśli naprawdę musi unikać lambda, można użyć anonimowego delegata (który @nowhewhomustnotbenamed już wymienionych):

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

Ale o co chodzi z tym? O wiele mniej czytelny!

+0

Właściwie to chcę uniknąć rzeczy Lambdy. – Bitterblue

+0

@ mini-me Cóż, dodałem przykład, który unika używania lambda ... Gorzej jest, IMO. –

+9

@ mini-ja Wyrażenia Lambda dość dawno zastąpiły anonimowych delegatów. Więc dobrze by się było przyzwyczaić do nich wcześniej niż później. – nashwan

2

Co na ten temat ?

class Program 
{ 
    static void Main(string[] args) 
    { 
     ThreadPool.QueueUserWorkItem(MyWork, "text"); 
     Console.ReadKey(); 
    } 

    private static void MyWork(object argument) 
    { 
     Console.WriteLine("Argument: " + argument); 
    } 
} 

Albo, jeśli nie chcą być podpis restrykcyjne i mieć prosty sposób na wprowadzenie metody na nitce można to zrobić jak this.For metod, które wykonują i nie zwraca wartości i mieć maksymalnie 6 parametry wymagałyby zdefiniowania 12 przeciążeń, jeśli się nie mylę.Wymaga nieco więcej pracy z góry, ale jest łatwiejszy w użyciu.

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

Byłby to dla mnie zwycięzca, gdyby nie był tak restrykcyjny. Ale wciąż fajnie jest po prostu nadać mu odpowiednią metodę i skończyć z nią. – Bitterblue

+0

@Bitterblue Dodałem drugie podejście. Trochę więcej pracy z góry, ale najprostsze w użyciu w mojej opinii. –