最简洁的异步调用void方法的方法

时间:2009-07-08 15:49:11

标签: c# asynchronous delegates code-golf

我有一个我想异步调用的方法:

void Foo()
{
}

我确实可以通过以下方式异步调用它:

delegate void DVoidMethod();
DVoidMethod FooDelegate = new DVoidMethod(Foo);
FooDelegate.BeginInvoke(null,null);

有没有人有其他选择?

我认为三行代码太多了?

6 个答案:

答案 0 :(得分:10)

声明:

请勿在实际代码中使用此功能。这只是为了缩短提到的代码OP。要在不获得结果的情况下执行真正的异步调用,请使用:

ThreadPool.QueueUserWorkItem(stateObject => Foo());

在框架中使用ActionFunc个代表:

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.StartNewTask.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
    }