C#异步调用没有EndInvoke会? [英] C# Asynchronous call without EndInvoke?

查看:275
本文介绍了C#异步调用没有EndInvoke会?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下面的类作为一个例子。

 大众A级
{
   // ...
   无效美孚(S MYSTRUCT){...}
}大众B级
{
   公开测试;
   // ...
   酒吧无效()
   {
      小号MYSTRUCT =新S();
      test.Foo(MYSTRUCT);
   }
}

现在,我想的方法调用test.Foo(MYSTRUCT)是一个异步调用(发射后不管)。酒吧-方法需要尽快返回。各地代表,BeginInvoke的,EndInvoke会,线程池等文档是没有帮助我找到一个解决方案。

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

  //使用`EndInvoke`方法作为回调委托有效的是什么?
     foo.BeginInvoke(MYSTRUCT,foo.EndInvoke,NULL);


解决方案

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


  • 您没有得到从方法的返回值。

  • 方法执行期间抛出的任何异常将简单地消失了。

这听起来像你想发射后不管,所以要做到这一点最简单的方法是使用匿名委托,例如:

  VAR德尔=新的行动(foo.Bar);
del.BeginInvoke(IAR = GT;
{
   尝试
   {
      del.EndInvoke(IAR);
   }
   赶上(异常前)
   {
      //记录消息?
   }
}, 空值);

这是当你执行这个code会发生什么:


  1. 一个新的线程分配(简单地说)的委托。

  2. 线程被赋予委托删除和匿名委托( IAR => ... )。

  3. 线程执行删除

  4. 当执行完毕(或者出现异常)的结果或异常存储并执行匿名委托。

  5. 在匿名委托,当 EndInvoke会被称为从方法的结果要么是返回,或抛出异常(如果发生的话)。

请注意,上述实施例是非常不同的

  //这是没有意义的,是静止的,基本上是同步。
del.EndInvoke(del.BeginInvoke(NULL,NULL));

编辑:您应该总是叫结束* 。我从来没有发现哪里都不称其为情景presents一个问题,但是这是一个实现细节,为的依靠无证行为。

最后,你的解决方案会崩溃的过程中,如果有异常抛出,<击>您可以简单地传递null作为代表,如果你不关心异常( del.BeginInvoke(MYSTRUCT,空,NULL); 所以当你正在寻找一个最后一个例子大概是:

 大众A级
{
    // ...
    无效美孚(S MYSTRUCT){...}
    无效FooAsync(S MYSTRUCT)
    {
        VAR德尔=新动作&LT; S&GT;(美孚);
        del.BeginInvoke(MYSTRUCT,燮pressException,德尔);
    }    静态无效燮pressException(IAsyncResult的AR)
    {
        尝试
        {
            ((动作&LT; S&GT;)ar.AsyncState).EndInvoke(AR);
        }
        抓住
        {
            // TODO:登录
        }
    }
}

Take the following classes as an example.

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

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

Now, I want the method-call test.Foo(myStruct) to be an asynchronous call ('fire-and-forget'). The bar-method needs to return as soon as possible. Documentation around delegates, BeginInvoke, EndInvoke, the ThreadPool etc. isn't helping me find a solution.

Is this a valid solution?

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

解决方案

You are not required to call EndInvoke; not calling it merely means:

  • You don't get the return value from the method.
  • Any exceptions thrown during the method execution will simply disappear.

It sounds like you want to 'fire-and-forget', so the easiest way to do this is to use an anonymous delegate, for example:

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

This is what happens when you execute this code:

  1. A new thread is allocated (put simply) for the delegate.
  2. The thread is given the delegate del and the anonymous delegate (iar => ...).
  3. The thread executes del.
  4. When it is finished executing (or an exception occurs) the result or exception is stored and the anonymous delegate is executed.
  5. Inside the anonymous delegate, when EndInvoke is called the result from the method is either returned, or the exception is thrown (if one occurred).

Note that the above example is very different from:

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

Edit: You should always call End*. I've never found a scenario where not calling it presents a problem, however that is an implementation detail and is relying on undocumented behavior.

Finally your solution would crash the process if an exception is thrown, you can simply pass null as the delegate if you don't care about the exception (del.BeginInvoke(myStruct, null, null);). So as a final example what you are looking for is probably:

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

这篇关于C#异步调用没有EndInvoke会?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆