gpt4 book ai didi

没有 EndInvoke 的 C# 异步调用?

转载 作者:可可西里 更新时间:2023-11-01 09:02:19 26 4
gpt4 key购买 nike

以下类为例。

public class A
{
// ...
void Foo(S myStruct){...}
}

public class B
{
public A test;
// ...
void Bar()
{
S myStruct = new S();
test.Foo(myStruct);
}
}

现在,我希望方法调用 test.Foo(myStruct) 成为异步调用(“即发即弃”)。 bar-method 需要尽快返回。有关委托(delegate)、BeginInvoke、EndInvoke、ThreadPool 等的文档无法帮助我找到解决方案。

这是一个有效的解决方案吗?

     // Is using the `EndInvoke` method as the callback delegate valid?
foo.BeginInvoke(myStruct, foo.EndInvoke, null);

最佳答案

您不需要调用EndInvoke;不调用它仅仅意味着:

  • 您没有从方法中获得返回值。
  • 方法执行期间抛出的任何异常都会消失。

听起来你想要“即发即弃”,所以最简单的方法是使用匿名委托(delegate),例如:

var del = new Action(foo.Bar);
del.BeginInvoke(iar =>
{
try
{
del.EndInvoke(iar);
}
catch (Exception ex)
{
// Log the message?
}
}, null);

这是执行这段代码时发生的情况:

  1. 为委托(delegate)分配(简单地说)一个新线程。
  2. 线程被赋予委托(delegate) del 和匿名委托(delegate) (iar => ...)。
  3. 线程执行del
  4. 当它完成执行(或发生异常)时,存储结果或异常并执行匿名委托(delegate)。
  5. 在匿名委托(delegate)内,当调用 EndInvoke 时,方法的结果要么返回,要么抛出异常(如果发生异常)。

请注意,上面的示例与以下示例有很大不同:

// This is pointless and is still, essentially, synchronous.
del.EndInvoke(del.BeginInvoke(null, null));

编辑:您应该始终调用End*。我从来没有发现不调用它会出现问题的情况,但这是一个实现细节并且是 relying on undocumented behavior.

最后,如果抛出异常,您的解决方案会使进程崩溃, 如果您不关心异常,您可以简单地将 null 作为委托(delegate)传递 ( del.BeginInvoke(myStruct, null, null) ;). 所以作为最后一个例子,你正在寻找的可能是:

public class A
{
// ...
void Foo(S myStruct){...}
void FooAsync(S myStruct)
{
var del = new Action<S>(Foo);
del.BeginInvoke(myStruct, SuppressException, del);
}

static void SuppressException(IAsyncResult ar)
{
try
{
((Action<S>)ar.AsyncState).EndInvoke(ar);
}
catch
{
// TODO: Log
}
}
}

关于没有 EndInvoke 的 C# 异步调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7492741/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com