Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 带反射的异步编程_C#_Silverlight_Asynchronous_Reflection.emit_Async Await - Fatal编程技术网

C# 带反射的异步编程

C# 带反射的异步编程,c#,silverlight,asynchronous,reflection.emit,async-await,C#,Silverlight,Asynchronous,Reflection.emit,Async Await,如何使用反射创建异步方法 基本上我需要这样的东西: async public Task asyncmethod() { await something(); } async public Task asyncmethod() { // some code var x = await something(); // more code } 但是我需要通过反射来实现。异步方法的转换在C#(或VB.NET)编译器的级别上工作,CIL中不支持它。在最简单的情况下,编译器

如何使用反射创建异步方法

基本上我需要这样的东西:

async public Task asyncmethod()
{
   await something();
}
async public Task asyncmethod()
{
    // some code
    var x = await something();
    // more code
}

但是我需要通过反射来实现。

异步方法的转换在C#(或VB.NET)编译器的级别上工作,CIL中不支持它。在最简单的情况下,编译器所做的是将代码翻译为如下所示:

async public Task asyncmethod()
{
   await something();
}
async public Task asyncmethod()
{
    // some code
    var x = await something();
    // more code
}
转换成基本上等同于以下内容的代码:

public Task asyncmethod()
{
   // some code
   return something().ContinueWith(
       t =>
       {
           var x = t.Result;
           // more code
       });
}
public async Task asyncmethod()
{
    Task t = ... // code that fetches the Task via reflection
    await t;
}
真正的代码比它复杂得多(它使用
同步上下文
,如果
某物()
返回已经完成的
任务
,它实际上不是异步的,它支持
等待
等待其他任务任务),而对于更复杂的C代码来说,它将更加复杂

但是,如果您真的想使用Reflection.Emit创建
异步
方法,那么您实际上必须手动执行此转换

但是需要注意的是,如果您的方法在返回之前只使用了一次
wait
,那么您可以将其重写为(假设
something()
返回一个
任务
,而不是
wait
可执行的其他内容):


解析问题的另一种方法是,您需要在方法中使用反射(例如,访问私有方法),但仍然希望使用wait

如果是这样的话,你可以像平常一样使用反射,把任务(或任何可以等待的东西)拿回来,然后分别等待

比如:

public Task asyncmethod()
{
   // some code
   return something().ContinueWith(
       t =>
       {
           var x = t.Result;
           // more code
       });
}
public async Task asyncmethod()
{
    Task t = ... // code that fetches the Task via reflection
    await t;
}

尽管如此,正如svick提到的,如果唯一的wait是在末尾,那么只返回任务,而不是将方法标记为async并使用wait。

async/wait是编译器构造。在CIL/ILGenerator/DynamicMethod世界中,它们并不以这种形式存在。async关键字和Wait运算符是更高级的语法。async用于标记一个方法,该方法允许您在可等待类型上进行等待。这些类型实现了GetAwaiter()——一种返回实现INotifyCompletion接口的类型的方法——例如Task/Task{T}——可以排队到TaskScheduler。它将在完成时调用INotifyCompletion.OnCompleted continuation

如果您想通过Reflection.Emit动态生成一个“async”方法,那么“所有”您需要做的就是返回您希望在其中等待的任务,返回到调用DynamicMethod的C#world。然后,您可以通过async/await对其进行等待。但问题是,您只能返回一个可等待项,因此在序列化可等待项时,例如:

await firstTask;
await secondTask;
await thirdTask;
// ...
await nTask;
除非可以将一个元组返回类型的多个等待项推送到堆栈上(我不知道如何为元组值设置callstack),然后调用wait result.Item1;等待结果。项目2。。。wait result.ItemN或推送列表{Task/Task{T}},您必须通过ContinueWith将每个连续的waitiable嵌套在每个先行的waitiable continuation中。我更喜欢返回列表{Task/Task{T}}所涉及的所有分配,而不是简单地将任务引用推到堆栈上。说到并行任务执行,我认为您无法避免列表{task/task{t}}示例:

Task DynamicQuoteAsyncUnquoteMethod()
{
    return firstAwaitedAsyncMethod()
        .ContinueWith(
            task =>
            {
                secondAwaitedAsyncMethod()
                    .ContinueWith(
                        task =>
                        {
                            thirdAwaitedAsyncMethod()
                                .ContinueWith(
                                task =>
                                {
                                    // yatta yatta
                                }
                        }
            }
        );
}

这意味着您必须为每个任务/任务{T}构建lambda。继续通过TypeBuilder调用,使用TypeBuilder.GetILGenerator()动态生成它,然后继续在父continuations中填充它们,直到您到达最连续的顶层,这将返回您可以等待的任务,这就是您需要返回调用动态创建的“async”方法的代码的全部内容。这将导致在前面的任务完成后,每个任务都会连续运行。

为什么要使用async/await?如果某物()返回一个任务,只需调用Wait on它。@PanagiotisKanavos,因为这将使方法同步,避免这是
async
的全部要点。你不能通过反射创建方法,你可以调用them@sleimanjneidi您可以使用Reflection.Emit.@PanagiotisKanavos,那里没有等待。他希望在运行时动态创建这样的方法。
async方法
在编译时不存在。请告诉我在哪里可以找到更多关于编译器如何使用async翻译代码的信息?我想等待的事情以外的任务,即使代码将更加复杂,我不知道有一个单一的明确的来源,描述目前的情况。最好的选择是C#5.0规范,但该规范尚未发布。有,也有。但他们中的大多数人都在谈论CTP,从那时起情况有所改变。尽管Jon Skeet系列的第18部分和第20部分分别讨论了CTP和DP之间以及DP和beta之间的变化。