Xamarin 跳过一个等待的方法

Posted

技术标签:

【中文标题】Xamarin 跳过一个等待的方法【英文标题】:Xamarin stepping over an awaitable method 【发布时间】:2017-11-16 17:12:39 【问题描述】:

在跨步 (F10) 的 WPF 应用程序中,一个等待的方法会将您带到下一行,但在 xamarin android 项目中,它的行为并非如此(就像我按下 F5 一样),我必须放置一个下一行的断点以便正确调试 - 这很痛苦 - 。

 async Task SomeMethod()
 
     await Task.Delay(1000); <--------- Stepping over this line leaves the function.
     int x = 1; <--------- I have to add a breakpoint here.
 

这是错误还是功能?

PS:我使用的是 Visual Studio 2017。

【问题讨论】:

使用 xamarin 的尴尬调试体验通常是一个错误。 Shift f11 通常会使调试器崩溃,而它曾经可以工作,直到单声道 5 出现。如果我是你,我会在 bugzilla.xamarin.com 上报告。希望他们最终修复它。与普通的 wpf 应用程序相比,调试肯定是一个皮塔 这可能是async 的一个特性——它只是超出了await 操作的方法范围,并继续在后台运行。也许,您应该关闭 Just My Code 复选框。 【参考方案1】:

确保您的方法是异步的。测试了我的,它在我身边工作。下面的例子:-

  Task.Run(async () =>
      
        await Task.Delay(1000); 
        int x = 1;
      );

async Task YourMethod
    
       await Task.Delay(1000); 
       int x = 1;
    

【讨论】:

你有什么版本的 Visual Studio?它在 Xamarin Droid 中吗? Visual Studio for Mac 的最新版本,是的,它是 Xamarin Droid。【参考方案2】:

不幸的是,这就是 Visual Studio 调试当前的工作方式。由于等待Task.Delay() 方法,程序流程返回到调用YourMethod() 的方法。如果该调用被等待,以及对该方法的调用链都在等待,以此类推,直到它到达应用程序上下文。例如。对于 Xamarin:

例如

 1 class MyActivity : Activity
 2 
 3     // This function is called by the Xamarin/Android systems and is not awaited.
 4     // As it is marked as async, any awaited calls within will pause this function,
 5     // and the application will continue with the function that called this function,
 6     // returning to this function when the awaited call finishes.
 7     // This means the UI is not blocked and is responsive to the user.
 8     public async void OnCreate()
 9     
10         base.OnCreate();
11         await initialiseAsync();  // awaited - so will return to calling function
12                                   // while waiting for operation to complete.
13
14         // Code here will run after initialiseAsync() has finished.
15     
16     public async Task initialiseAsync()
17     
18         await YourMethod();  // awaited - so will return to Line 11
19                              // while waiting for operation to complete.
20         
21         // Code here will run after GetNamesAsync() has finished.
22     
23 

在纯 Windows 应用程序中,Visual Studio 了解应用程序的所有上下文,并且知道不需要调试底层方法(程序生命周期、窗口事件、屏幕重绘等)(并且无法访问源代码) .您可能看到的是调试器暂停了 1000 毫秒,因为没有要调试的代码。

Xamarin 在其中添加了一层额外的代码,其中包括基本 Activity 类的实现和所有 Android 要求。 Visual Studio 不知道要跳过这些,因此尝试调试称为当前等待的方法堆栈的任何代码。这可能类似于基本 Activity 类的 OnCreate() 方法 - 您可能无法访问其代码。

【讨论】:

【参考方案3】:

这正是await 运算符的工作原理。当您awaitTask 时,代码执行将跳出当前函数并将控制权交给其调用者。然后在等待的Task 完成后的某个时间点,它会在await 语句之后跳回执行代码。

如果您跳过await,调试器会将您导航到将要执行的下一行代码。在await 的情况下,很可能不会是以下行。

【讨论】:

请在 WPF、Windows Forms 或 Windows Phone 中尝试代码,F10 将带您到“int x=1”,然后在 Xamarin.Forms 或 Android 中尝试它不会。 @voytasify 这不是 await 是如何工作的。 Await 将立即执行使用await 关键字调用的方法,并执行方法内部的代码。仅当在被调用方法(或其被调用方法)中调用其他(通常是 I/O 绑定)操作时,等待它们自己的结果(也通过使用await 调用方法或返回Task),当前线程可能会被调度程序重新利用一段时间。因此,单步执行一个等待的方法应该总是有效的,就像跨过一个方法一样。

以上是关于Xamarin 跳过一个等待的方法的主要内容,如果未能解决你的问题,请参考以下文章

在返回导航中跳过 xamarin 表单中的页面

Xamarin iOS:等待 HKHealthStore SaveObject 完成

Xamarin iOS:等待 HKHealthStore SaveObject 完成

使用异步等待 C# Xamarin

Xamarin:NSInvalidReceivePortException:在等待回复时连接无效,因为一个马赫端口死了

在 c# Xamarin 中等待带有弹出窗口的任务