Почему этот асинхронный метод C# 4.0 не вызывается?
Я пытаюсь написать действительно простой бит асинхронного кода. У меня есть метод void, который не принимает никаких параметров, который должен вызываться из службы Windows. Я хочу запустить его асинхронно, чтобы служба не зависала в ожидании завершения метода.
Я создал очень простое тестовое приложение, чтобы убедиться в правильности написания кода, но асинхронный метод просто не вызывается. Кто-нибудь может увидеть, что я сделал не так? Кстати, я использую.NET 4.0, поэтому я не могу использовать await (что было бы намного проще!).
Вот весь мой тестовый образец...
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");
}
}
}
Спасибо за любую помощь, которую вы можете оказать.
4 ответа
Ваша программа завершает работу до того, как асинхронный метод будет развернут в ThreadPool
, Держите вашу программу открытой на некоторое время. возможно Console.ReadKey()
в конце Main
?
Любое приложение завершится, как только не появятся потоки переднего плана, которые не завершили выполнение. Если есть какие-либо фоновые потоки, они не будут поддерживать процесс "живым".
Поскольку вы запускаете асинхронную задачу в фоновом режиме и ничто не мешает выполнению потока переднего плана, весь процесс завершается.
Вам либо нужно запустить асинхронную задачу в потоке переднего плана (что нельзя сделать с помощью BeginInvoke
насколько я знаю, вам нужно создать новый Thread
явно) или сделать что-то еще, чтобы заблокировать основной поток до его завершения.
Вы не ждете завершения, поэтому попробуйте что-то вроде этого
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");
Для начала ваш обратный вызов не является правильным делегатом... Это должно быть
public delegate void AsyncCallback(IAsyncResult ar);
И твой
private static void StuffDone()
Просто измените это на что-то вроде этого:
private static void StuffDone(IAsyncResult ar){}
А затем в вашем обратном звонке убедитесь, что Действие действительно выполняется, вызвав
EndInvoke
на AsyncState
Как это:
private static void StuffDone(IAsyncResult ar)
{
Action r = ar.AsyncState as Action;
r.EndInvoke(ar);
Console.WriteLine(DateTime.Now.ToLocalTime().ToLongTimeString() + " - Stuff done");
}
Еще одно изменение, которое вам нужно сделать, это когда вы создаете экземпляр Action в главной функции, передаете само действие как аргумент 'object' объекта BeginInvoke
метод как это:
Action d = new Action(DoStuff);
d.BeginInvoke(StuffDone, d);
это должно решить вашу проблему:)