2012-12-10 20 views
5

Próbuję napisać naprawdę prosty kod asynchroniczny. Mam metodę void, która nie przyjmuje żadnych parametrów, które mają być wywołane z usługi Windows. Chcę to zsynchronizować tak, aby usługa nie musiała czekać, aż metoda się zakończy.Dlaczego ta asynchroniczna metoda C# 4.0 nie jest wywoływana?

Stworzyłem bardzo prostą aplikację testową, aby upewnić się, że robię prawo do kodowania, ale metoda asynchroniczna po prostu nie jest wywoływana. Czy ktoś może zobaczyć, co zrobiłem źle? Używam przy okazji .NET 4.0, więc nie mogę się już doczekać (co byłoby o wiele prostsze!).

Oto cała moja próbka testowa ...

using System; 
using System.Threading; 

namespace AsyncCallback { 
    internal class Program { 
    private static void Main(string[] args) { 
     Console.WriteLine(DateTime.Now.ToLocalTime().ToLongTimeString() + " - About to ask for stuff to be done"); 
     new Action(DoStuff).BeginInvoke(ar => StuffDone(), null); 
     Console.WriteLine(DateTime.Now.ToLocalTime().ToLongTimeString() + " - Asked for stuff to be done"); 
    } 

    private static void StuffDone() { 
     Console.WriteLine(DateTime.Now.ToLocalTime().ToLongTimeString() + " - Stuff done"); 
    } 

    private static void DoStuff() { 
     Console.WriteLine(DateTime.Now.ToLocalTime().ToLongTimeString() + " - Starting to do stuff"); 
     Thread.Sleep(1000); 
     Console.WriteLine(DateTime.Now.ToLocalTime().ToLongTimeString() + " - Ending doing stuff"); 
    } 
    } 
} 

Dzięki za wszelką pomoc można dać.

+0

@Martin: gdzie jest 'async' /' await' w pytaniu powyżej? – spender

+0

Dlaczego nie używać .NET 4.5? – Rafael

+0

@spender Używał "async" jako ogólnego skrótu celu "asynchroniczny" w przeciwieństwie do słowa kluczowego C#. – Servy

Odpowiedz

6

Twój program kończy pracę, zanim metoda asynchroniczna zostanie wdrożona w ThreadPool. Zachowaj swój program nieco otwarty. Być może Console.ReadKey() na końcu Main?

+0

Duh, oczywiste! Dziękuję za to. Robiłem to w projekcie testowym, więc po wywołaniu asynchronicznym nic się nie działo. Zapomniałem, że wątek zakończy się całkowicie. Dzięki. –

5

Dowolna aplikacja zostanie zakończona, gdy tylko nie będzie żadnych nowych wątków , które nie zostały jeszcze wykonane. Jeśli są jakieś wątki w tle, nie utrzymają procesu "żywy".

Ponieważ uruchamiasz zadanie asynchroniczne w tle, a nic nie utrzymuje wątku pierwszoplanowego, cały proces jest zamykany.

Zamiast tego musisz uruchomić swoje asynchroniczne zadanie w wątku pierwszoplanowym (co nie może być wykonane z BeginInvoke, o ile wiem, musisz jawnie utworzyć nowy Thread) lub zrobić coś innego, aby zablokować główny wątek, aż się zakończy.

+0

Dzięki Servy, jak spender, odpowiedziałeś na pytanie :) –

1

Nie czekają na ukończeniu, więc spróbować czegoś jak ten

Console.WriteLine(DateTime.Now.ToLocalTime().ToLongTimeString() + " - About to ask for stuff to be done"); 
var a = new Action(DoStuff); 
var iar = a.BeginInvoke(ar => StuffDone(), null); 
a.EndInvoke(iar); 
Console.WriteLine(DateTime.Now.ToLocalTime().ToLongTimeString() + " - Asked for stuff to be done"); 
+0

chociaż jeśli masz zamiar po prostu poczekać na wyniki zadania asynchronicznego, po co je uruchamiać asynchronicznie w pierwszej kolejności ... – Servy

1

Aby rozpocząć z, twój zwrotna nie jest poprawna delegat ... Powinno być

public delegate void AsyncCallback(IAsyncResult ar); 

i twoje jest

private static void StuffDone() 

Wystarczy zmienić go na coś takiego:

private static void StuffDone(IAsyncResult ar){} 

A potem w oddzwaniania upewnić się, że działanie rzeczywiście wykonywany przez wywołanie

EndInvoke 

na AsyncState

tak:

private static void StuffDone(IAsyncResult ar) 
{ 
    Action r = ar.AsyncState as Action; 
    r.EndInvoke(ar); 

    Console.WriteLine(DateTime.Now.ToLocalTime().ToLongTimeString() + " - Stuff done"); 
} 

One więcej zmian trzeba to make, kiedy tworzysz akcję w głównej funkcji, przekazuj akcję jako argument "obiektu" BeginInvoke metoda tak:

Action d = new Action(DoStuff); 
d.BeginInvoke(StuffDone, d); 

to powinno rozwiązać problem :)