<tfoot id='DIimL'></tfoot>
    <legend id='DIimL'><style id='DIimL'><dir id='DIimL'><q id='DIimL'></q></dir></style></legend>
    • <bdo id='DIimL'></bdo><ul id='DIimL'></ul>

    <small id='DIimL'></small><noframes id='DIimL'>

      <i id='DIimL'><tr id='DIimL'><dt id='DIimL'><q id='DIimL'><span id='DIimL'><b id='DIimL'><form id='DIimL'><ins id='DIimL'></ins><ul id='DIimL'></ul><sub id='DIimL'></sub></form><legend id='DIimL'></legend><bdo id='DIimL'><pre id='DIimL'><center id='DIimL'></center></pre></bdo></b><th id='DIimL'></th></span></q></dt></tr></i><div id='DIimL'><tfoot id='DIimL'></tfoot><dl id='DIimL'><fieldset id='DIimL'></fieldset></dl></div>

        C# 中的类型安全即发即弃异步委托调用

        时间:2023-11-11
      1. <small id='zInpJ'></small><noframes id='zInpJ'>

        <legend id='zInpJ'><style id='zInpJ'><dir id='zInpJ'><q id='zInpJ'></q></dir></style></legend>
          <tbody id='zInpJ'></tbody>

                <tfoot id='zInpJ'></tfoot>

              • <i id='zInpJ'><tr id='zInpJ'><dt id='zInpJ'><q id='zInpJ'><span id='zInpJ'><b id='zInpJ'><form id='zInpJ'><ins id='zInpJ'></ins><ul id='zInpJ'></ul><sub id='zInpJ'></sub></form><legend id='zInpJ'></legend><bdo id='zInpJ'><pre id='zInpJ'><center id='zInpJ'></center></pre></bdo></b><th id='zInpJ'></th></span></q></dt></tr></i><div id='zInpJ'><tfoot id='zInpJ'></tfoot><dl id='zInpJ'><fieldset id='zInpJ'></fieldset></dl></div>
                • <bdo id='zInpJ'></bdo><ul id='zInpJ'></ul>
                  本文介绍了C# 中的类型安全即发即弃异步委托调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  我最近发现自己需要一种类型安全的即发即弃"机制来异步运行代码.

                  理想情况下,我想做的是:

                  Ideally, what I would want to do is something like:

                  var myAction = (Action)(() => Console.WriteLine("yada yada"));
                  myAction.FireAndForget(); // async invocation
                  

                  不幸的是,在没有相应 EndInvoke() 的情况下调用 BeginInvoke() 的明显选择不起作用 - 它会导致缓慢的资源泄漏(因为异步状态是由运行时持有并且从未释放...它期望最终调用 EndInvoke().我也无法在 .NET 线程池上运行代码,因为它可能需要很长时间才能完整(建议只在线程池上运行相对短暂的代码) - 这使得无法使用 ThreadPool.QueueUserWorkItem().

                  Unfortunately, the obvious choice of calling BeginInvoke() without a corresponding EndInvoke() does not work - it results in a slow resource leak (since the asyn state is held by the runtime and never released ... it's expecting an eventual call to EndInvoke(). I also can't run the code on the .NET thread pool because it may take a very long time to complete (it's advised to only run relatively short-lived code on the thread pool) - this makes it impossible to use the ThreadPool.QueueUserWorkItem().

                  最初,我只需要签名匹配 ActionAction<...>Func<...> 的方法使用此行为..所以我把一组扩展方法(见下面的清单)放在一起,让我在不遇到资源泄漏的情况下做到这一点.每个版本的 Action/Func 都有重载.

                  Initially, I only needed this behavior for methods whose signature matches Action, Action<...>, or Func<...>. So I put together a set of extension methods (see listing below) that let me do this without running into the resource leak. There are overloads for each version of Action/Func.

                  不幸的是,我现在想将此代码移植到 .NET 4,其中 Action 和 Func 的泛型参数数量已大大增加.在我编写一个 T4 脚本来生成这些之前,我还希望找到一种更简单更优雅的方法来做到这一点.欢迎任何想法.

                  Unfortunately, I now want to port this code to .NET 4 where the number of generic parameters on Action and Func have been increased substantially. Before I write a T4 script to generate these, I was also hoping to find a simpler more elegant way to do this. Any ideas are welcome.

                  public static class AsyncExt
                  {
                      public static void FireAndForget( this Action action )
                      {
                          action.BeginInvoke(OnActionCompleted, action);
                      }
                  
                      public static void FireAndForget<T1>( this Action<T1> action, T1 arg1 )
                      {
                          action.BeginInvoke(arg1, OnActionCompleted<T1>, action);
                      }
                  
                      public static void FireAndForget<T1,T2>( this Action<T1,T2> action, T1 arg1, T2 arg2 )
                      {
                          action.BeginInvoke(arg1, arg2, OnActionCompleted<T1, T2>, action);
                      }
                  
                      public static void FireAndForget<TResult>(this Func<TResult> func, TResult arg1)
                      {
                          func.BeginInvoke(OnFuncCompleted<TResult>, func);
                      }
                  
                      public static void FireAndForget<T1,TResult>(this Func<T1, TResult> action, T1 arg1)
                      {
                          action.BeginInvoke(arg1, OnFuncCompleted<T1,TResult>, action);
                      }
                  
                      // more overloads of FireAndForget<..>() for Action<..> and Func<..>
                  
                      private static void OnActionCompleted( IAsyncResult result )
                      {
                          var action = (Action)result.AsyncState;
                          action.EndInvoke(result);
                      }
                  
                      private static void OnActionCompleted<T1>( IAsyncResult result )
                      {
                          var action = (Action<T1>)result.AsyncState;
                          action.EndInvoke( result );
                      }
                  
                      private static void OnActionCompleted<T1,T2>(IAsyncResult result)
                      {
                          var action = (Action<T1,T2>)result.AsyncState;
                          action.EndInvoke(result);
                      }
                  
                      private static void OnFuncCompleted<TResult>( IAsyncResult result )
                      {
                          var func = (Func<TResult>)result.AsyncState;
                          func.EndInvoke( result );
                      }
                  
                      private static void OnFuncCompleted<T1,TResult>(IAsyncResult result)
                      {
                          var func = (Func<T1, TResult>)result.AsyncState;
                          func.EndInvoke(result);
                      }
                  
                      // more overloads of OnActionCompleted<> and OnFuncCompleted<>
                  
                  }
                  

                  推荐答案

                  您可以将 EndInvoke 作为 AsyncCallback 传递给 BeginInvoke:

                  You can pass EndInvoke as AsyncCallback for BeginInvoke:

                  Action<byte[], int, int> action = // ...
                  
                  action.BeginInvoke(buffer, 0, buffer.Length, action.EndInvoke, null);
                  

                  这有帮助吗?

                  这篇关于C# 中的类型安全即发即弃异步委托调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                    <tbody id='1CAbF'></tbody>
                      <i id='1CAbF'><tr id='1CAbF'><dt id='1CAbF'><q id='1CAbF'><span id='1CAbF'><b id='1CAbF'><form id='1CAbF'><ins id='1CAbF'></ins><ul id='1CAbF'></ul><sub id='1CAbF'></sub></form><legend id='1CAbF'></legend><bdo id='1CAbF'><pre id='1CAbF'><center id='1CAbF'></center></pre></bdo></b><th id='1CAbF'></th></span></q></dt></tr></i><div id='1CAbF'><tfoot id='1CAbF'></tfoot><dl id='1CAbF'><fieldset id='1CAbF'></fieldset></dl></div>

                      <small id='1CAbF'></small><noframes id='1CAbF'>

                      <legend id='1CAbF'><style id='1CAbF'><dir id='1CAbF'><q id='1CAbF'></q></dir></style></legend>
                      <tfoot id='1CAbF'></tfoot>

                        <bdo id='1CAbF'></bdo><ul id='1CAbF'></ul>