GetResults()方法和await关键字之间的区别

时间:2014-04-23 17:58:44

标签: c# windows asynchronous async-await

编辑问题:在C#中,当使用DataWriter对象时,为什么“await dataWriter.StoreAsync()”在“dataWriter.StoreAsync()。GetResults()”导致First Chance异常时起作用。从我如何理解GetResults()方法和await关键字,它们应该在这种情况下正常运行。我想了解GetResults()方法和await关键字之间的区别,以了解为什么一个有效,一个不在这种特殊情况下。

如果我有一个FileStorage对象并使用await关键字调用DeleteAsync()方法(等待fs.DeleteAsync())它可以正常工作但是如果我使用GetResults()方法(fs.DeleteAsync()。GetResults() )我经常得到InvalidOperationException类型的“First Chance Exceptions”。

我试图理解为什么await关键字在这里运行正常,但是GetResults()方法没有(当我相信它们在这种特殊情况下都能正常工作时)所以我可以更好地掌握何时应该使用GetResults ()方法和何时应该使用“await”关键字。这适用于Windows 8 Metro应用程序。 感谢

编辑(从我的测试项目中添加代码)

private async void SavePressed(object sender, RoutedEventArgs e)
        {

            RenderTargetBitmap rtb = new RenderTargetBitmap();
            await rtb.RenderAsync(SignatureCanvas);

            IBuffer pBuffer = await rtb.GetPixelsAsync();
            byte[] pixels = pBuffer.ToArray();

            var fileName = "sig.png";
            var folder = Windows.Storage.ApplicationData.Current.LocalFolder;

            StorageFile file = await folder.CreateFileAsync(fileName, Windows.Storage.CreationCollisionOption.ReplaceExisting);

            Debug.WriteLine("----" + file.Path);
            DisplayInformation dispInfo = DisplayInformation.GetForCurrentView();
            using (var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite))
            {
                BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
                encoder.SetPixelData(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Straight, (uint)rtb.PixelWidth, (uint)rtb.PixelHeight, dispInfo.LogicalDpi, dispInfo.LogicalDpi, pixels);
                await encoder.FlushAsync();
            }

            Debug.WriteLine(file.Path);

            saveSigToDB(file);

            await file.DeleteAsync();
        //    file.DeleteAsync().GetResults();

        }


private async void loadPressed(object sender, Windows.UI.Xaml.RoutedEventArgs e)
        {
            // TODO: Add event handler implementation here.
            DataStoreHelper dataHelper = DataStoreHelper.Instance;
            Signature sig = await dataHelper.getSignature(1);

            Debug.WriteLine("----" + sig.name);
            Debug.WriteLine("----" + sig.imgData);
            Debug.WriteLine("----" + sig.imgData.Length);

            InMemoryRandomAccessStream ims = new InMemoryRandomAccessStream();
            byte[] bytes = Convert.FromBase64String(sig.imgData);

            DataWriter dataWriter = new DataWriter(ims);

            dataWriter.WriteBytes(bytes);
          //  dataWriter.StoreAsync().GetResults();
            await dataWriter.StoreAsync();
            ims.Seek(0);
            BitmapImage image = new BitmapImage();
            image.SetSource(ims);
            SigImage.Source = image;


        }

EDIT2:为FileStorage DeleteAsync()方法添加了调试输出,这是你要找的?我无法重现StoreAsync(),因为它现在似乎正在使用await关键字或GetResults()方法正常工作,但不确定为什么if if之前没有工作。

'Test Signature.exe' (CLR v4.0.30319: DefaultDomain): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Test Signature.exe' (CLR v4.0.30319: DefaultDomain): Loaded 'C:\Users\Tester\Documents\Visual Studio 2013\Projects\Test Signature\Test Signature\bin\x64\Debug\AppX\Test Signature.exe'. Symbols loaded.
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Runtime\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Runtime.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\system32\WinMetadata\Windows.UI.Xaml.winmd'. Module was built without symbols.
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Runtime.InteropServices.WindowsRuntime\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Runtime.InteropServices.WindowsRuntime.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\system32\WinMetadata\Windows.ApplicationModel.winmd'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\system32\WinMetadata\Windows.Foundation.winmd'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Runtime.WindowsRuntime\v4.0_4.0.0.0__b77a5c561934e089\System.Runtime.WindowsRuntime.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Runtime.WindowsRuntime.UI.Xaml\v4.0_4.0.0.0__b77a5c561934e089\System.Runtime.WindowsRuntime.UI.Xaml.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\system32\WinMetadata\Windows.UI.winmd'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Diagnostics.Debug\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Diagnostics.Debug.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\system32\WinMetadata\Windows.Globalization.winmd'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Collections\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Collections.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\system32\WinMetadata\Windows.System.winmd'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\system32\WinMetadata\Windows.Devices.winmd'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Runtime.Extensions\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Runtime.Extensions.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Threading.Tasks\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Threading.Tasks.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\system32\WinMetadata\Windows.Storage.winmd'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\system32\WinMetadata\Windows.Graphics.winmd'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Configuration\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Configuration.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Xml\v4.0_4.0.0.0__b77a5c561934e089\System.Xml.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
----C:\Users\Tester\AppData\Local\Packages\a0c18bed-2eed-43e5-b052-d85765e6e8b1_fgj28ymhhr2yg\LocalState\sig.png
C:\Users\Tester\AppData\Local\Packages\a0c18bed-2eed-43e5-b052-d85765e6e8b1_fgj28ymhhr2yg\LocalState\sig.png
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Threading\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Threading.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Text.Encoding\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Text.Encoding.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
here
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Linq\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Linq.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Core\v4.0_4.0.0.0__b77a5c561934e089\System.Core.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
A first chance exception of type 'System.InvalidOperationException' occurred in Test Signature.exe
WinRT information: A method was called at an unexpected time.
'Test Signature.exe' (CLR v4.0.30319: Immersive Application Domain): Loaded 'C:\Windows\assembly\GAC_MSIL\Microsoft.VisualStudio.Debugger.Runtime\12.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.Debugger.Runtime.DLL'.
编辑3:我相信我抓住了你想要的东西。我根据这篇文章捕获了它:How do I find the stack trace in Visual Studio?

>   Test Signature.exe!Test_Signature.App.InitializeComponent.AnonymousMethod__1(object sender, Windows.UI.Xaml.UnhandledExceptionEventArgs e) Line 50  C#

1 个答案:

答案 0 :(得分:4)

您所指的GetResults来自IAsyncOperation(T)

当您调用GetResults时,操作将同步运行,直到操作完成。当对象继承自Close时,应该跟IAsyncInfo

TResult result;
DataWriterStoreOperation task = dw.StoreAsync();

try
{
    result = task.GetResults();
}
finally
{
    task.Close();
}

IAsyncOperation(T)上使用await运算符暂停执行状态直到它完成。

WinRT平台上推荐的方法是在应用程序的所有级别使用asyncawait。在使用旧的非异步代码时,您将使用手动方法。

TResult result = await dw.StoreAsync();

对于您的实施,您可以参考C# Windows 8 Store (Metro, WinRT) Byte array to BitmapImage

private async void loadPressed(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
    // TODO: Add event handler implementation here.
    DataStoreHelper dataHelper = DataStoreHelper.Instance;
    Signature sig = await dataHelper.getSignature(1);

    Debug.WriteLine("----" + sig.name);
    Debug.WriteLine("----" + sig.imgData);
    Debug.WriteLine("----" + sig.imgData.Length);

    byte[] bytes = Convert.FromBase64String(sig.imgData);

    SigImage.Source = await ByteArrayToBitmapImage(bytes);
}

private async Task<BitmapImage> ByteArrayToBitmapImage(byte[] byteArray)
{
    var bitmapImage = new BitmapImage();

    var stream = new InMemoryRandomAccessStream();
    await stream.WriteAsync(byteArray.AsBuffer());
    stream.Seek(0);

    bitmapImage.SetSource(stream);
    return bitmapImage;
}

确保在应用程序暂停时丢弃SigImage.Source并在恢复时重新加载。

另见:

What is the difference between Task<> and IAsyncOperation<>

What are the risks of wrapping Async/Await IAsyncOperations with Task.Wait() code?

要将IAsyncOperation(T)转换为Task(T),请使用扩展方法AsTask