Почему этот асинхронный метод 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);

это должно решить вашу проблему:)

Другие вопросы по тегам