5

我正在尝试编写一段非常简单的异步代码。我有一个不带任何参数的 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

4 回答 4

6

您的程序在异步方法部署到ThreadPool. 让您的程序保持打开状态。也许Console.ReadKey()在年底Main

于 2012-12-10T19:21:19.883 回答
5

只要没有未完成执行的前台线程,任何应用程序都将结束。如果有任何后台线程,它们将不会使进程保持“活动”。

因为您在后台启动异步任务,并且没有任何东西保持前台线程运行,所以整个进程正在退出。

您要么需要在前台线程中运行您的异步任务(据我所知,这无法完成BeginInvoke,您需要Thread显式创建一个新线程)或执行其他操作来阻止主线程,直到它完成。

于 2012-12-10T19:22:38.723 回答
1

你不是在等待完成,所以试试这样的

 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");
于 2012-12-10T19:26:13.847 回答
1

首先,您的回调不是正确的委托......它应该是

public delegate void AsyncCallback(IAsyncResult ar);

而你的是

private static void StuffDone()

只需将其更改为以下内容:

private static void StuffDone(IAsyncResult ar){}

然后在您的回调中确保 Action 通过调用实际执行

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

您需要进行的另一项更改是,当您在主函数中实例化动作时,将动作本身作为BeginInvoke方法的“对象”参数传递,如下所示:

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

这应该可以解决您的问题:)

于 2012-12-10T19:35:45.723 回答