为什么这个C# 4.0异步方法没有被调用?

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

感谢您能够提供的任何帮助。
谢谢。

@Martin: 上面的问题中async/await在哪里? - spender
@spender 他使用“async”作为通用缩写,表示异步操作,而不是C#关键字。 - Servy
1
顺便提一下,你可以使用ThreadPool.QueueUserWorkItem而不是使用委托(Action),甚至更好的方法是了解System.Threading.Tasks命名空间中的类型。这将是你时间更好的投资。 - Panos Rontogiannis
Rafael,我没有使用.NET 4.5,因为真正的代码将部署在没有安装它的服务器上。 - Avrohom Yisroel
4个回答

6

您的程序在异步方法部署到ThreadPool之前就终止了。请将程序保持打开状态一段时间,例如在Main方法结尾处加入Console.ReadKey()?


噢,显而易见!谢谢您的提醒。我在一个测试项目中执行这个操作,所以在异步调用之后没有其他任务。忘记了该线程会完全结束。非常感谢。 - Avrohom Yisroel

5
任何应用程序在没有未完成执行的前台线程时将结束。如果有任何后台线程,它们不会保持进程“活动”。
由于您在后台启动异步任务,没有任何东西可以使前台线程运行,整个进程正在退出。
您需要将异步任务在前台线程中运行(我所知道的不能使用BeginInvoke来实现,您需要显式创建一个新的Thread),或者做一些其他事情来阻止主线程直到它完成。

谢谢Servy,就像spender一样,你回答了这个问题 :) - Avrohom Yisroel

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

虽然如果你只是等待异步任务的结果,为什么要先异步启动它呢... - Servy

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

你还需要做的一个更改是,在主函数中实例化Action时,将Action本身作为BeginInvoke方法的“object”参数传递,像这样:

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

这应该能解决你的问题 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接