我有一个我想异步调用的方法:
void Foo()
{
}
我确实可以通过以下方式异步调用它:
delegate void DVoidMethod();
DVoidMethod FooDelegate = new DVoidMethod(Foo);
FooDelegate.BeginInvoke(null,null);
有没有人有其他选择?
我觉得三行代码太多了?
我有一个我想异步调用的方法:
void Foo()
{
}
我确实可以通过以下方式异步调用它:
delegate void DVoidMethod();
DVoidMethod FooDelegate = new DVoidMethod(Foo);
FooDelegate.BeginInvoke(null,null);
有没有人有其他选择?
我觉得三行代码太多了?
不要在实际代码中使用它。这只是试图缩短提到的代码 OP。要在不返回结果的情况下进行真正的异步调用,请使用:
ThreadPool.QueueUserWorkItem(stateObject => Foo());
在框架中使用Action
和委托:Func
new Action(Foo).BeginInvoke(null, null);
Action<T>
自 2.0 以来一直存在。3.5 中添加了其他变体。但是,在 2.0 上,您可以在某处手动声明一堆以供进一步使用;甚至更好,使用LINQBridge。
怎么样:
ThreadPool.QueueUserWorkItem(new WaitCallback((o) => Foo()));
更新以考虑较新版本的 .net 中可用的 TPL API:
在.Net 4及更高版本中,您可以执行以下操作:
Task.Factory.StartNew(() => Foo());
在.Net 4.5及更高版本中,您还可以执行以下操作:
Task.Run(() => Foo());
Task.Factory.StartNew和Task.Run之间的区别在于,“StartNew”方法有一些额外的参数,可以让您传递状态、任务创建选项和调度程序,以便在需要时为您提供一些额外的控制。
您可以将其分解为两行(在 .Net 1.1及更早版本中),只需:
delegate void DVoidMethod();
new FooDelegate(DVoidMethod).BeginInvoke(null, null)
但在 2.0 及更高版本中……Mehrdad 的语法有效。
请参阅 MSDN 上 2.0 及更高版本的操作委托:
http://msdn.microsoft.com/en-us/library/018hxwa8(VS.80).aspx
如果不使用 Action 和 Func,您可以在 void () 委托的情况下使用 MethodInvoker:
new MethodInvoker(Foo).BeginInvoke(null, null);
另外,应该注意的是,如果您使用 BeginInvoke 方法,则必须在委托完成执行时调用 EndInvoke。因此,上面的这一行必须更改为使用回调,或者您需要保留对委托的引用。 . 像这样:
MethodInvoker mi = null;
IAsyncResult ar = null;
ar = (mi = new MethodInvoker(Foo)).BeginInvoke(null,null);
.. sometime later after the delegate has completed executing
mi.EndInvoke(ar);
每当您使用 BeginInvoke 时都是如此。所以我想最后我不会推荐使用 BeginInvoke 方法..
@Steven 使用 ThreadPool的解决方案在我看来是一个更好的解决方案.. 和他的 oviously:)
严格来说,从性能的角度来看,我不会担心代码行数,因为您不知道您正在调用的函数背后有多少实际代码。
旧线程,但我无法抗拒堆积。
您确实必须调用 EndInvoke 以避免泄漏,即使您没有使用结果或对方法的完成做出反应。但这并不意味着它必须是丑陋的。
BeginInvoke 需要 AsyncCallback 作为回调参数。AsyncCallback 的签名是一个带有 IAsyncResult 的 void。EndInvoke 具有该签名,因此:
//waste some time...
void Foo() {}
void InvokeFoo()
{
Action fooer = () => Foo();
fooer.BeginInvoke(fooer.EndInvoke, null);
}
void InvokeFoo2()
{
// or, less concise but some consider more readable:
Action fooer = new Action(Foo); //...invoke doesn't change
}