我有一个我想异步调用的方法:
void Foo()
{
}
我确实可以通过以下方式异步调用它:
delegate void DVoidMethod();
DVoidMethod FooDelegate = new DVoidMethod(Foo);
FooDelegate.BeginInvoke(null,null);
有没有人有其他选择?
我认为三行代码太多了?
答案 0 :(得分:10)
请勿在实际代码中使用此功能。这只是为了缩短提到的代码OP。要在不获得结果的情况下执行真正的异步调用,请使用:
ThreadPool.QueueUserWorkItem(stateObject => Foo());
在框架中使用Action
和Func
个代表:
new Action(Foo).BeginInvoke(null, null);
Action<T>
自2.0以来一直存在。其他变种在3.5中添加。但是,在2.0中,您可以手动将其中一堆声明用于进一步使用;甚至更好,使用LINQBridge。
答案 1 :(得分:8)
怎么样:
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'方法有一些额外的参数,可让您通过状态,任务创建选项和调度程序,以便在需要时为您提供额外的控制
答案 2 :(得分:3)
你可以简单地将其分为两行(在.Net 1.1 和更早版本中):
delegate void DVoidMethod();
new FooDelegate(DVoidMethod).BeginInvoke(null, null)
但在2.0及更高版本中...... Mehrdad的语法有效。
请参阅MSDN上的2.0及更高版本的Action delegate:
http://msdn.microsoft.com/en-us/library/018hxwa8(VS.80).aspx
答案 3 :(得分:3)
在不使用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是一个更好的解决方案在我看来......而且他显然是:)
答案 4 :(得分:1)
严格来说,我不担心从性能角度来看代码行的数量,因为你不知道你正在调用的函数背后有多少实际代码。
答案 5 :(得分:1)
旧线程,但我无法抗拒堆积。
您确实必须调用EndInvoke以避免泄漏,即使您没有使用结果或对方法的完成做出反应。但这并不意味着它必须是丑陋的。
BeginInvoke期望AsyncCallback作为回调参数。 AsyncCallback的签名是一个带有IAsyncResult的空白。 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
}