原文如下。让我尝试更详细地解释我为什么要这样做。
我有一个收听分享魅力请求的页面:
void Page_Loaded(object sender, RoutedEventArgs e)
{
m_transferManager = Windows.ApplicationModel.DataTransfer.DataTransferManager.GetForCurrentView();
m_transferManager.DataRequested += TransferManager_DataRequested;
}
当事件触发 ( TransferManager_DataRequested
) 时,它不会在 UI 线程上触发:
void TransferManager_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
var data = args.Request.Data;
// More related stuff omitted - not important.
data.SetDataProvider(StandardDataFormats.Bitmap, GetImage_DelayRenderer);
}
现在,当GetImage_DelayRender
被调用时,它也不会在 UI 线程上被调用。但是,在其中,我需要做一堆与 UI 相关的事情。具体来说,我需要调用一个仅适用于 UI 的方法(这是我在其他地方使用的方法,我想重用它的逻辑)。该方法被调用GetImageAsync
并且它需要在 UI 上运行,因为它与 WriteableBitmap 进行了一堆交互。它还执行一堆异步操作(例如写入流等),这就是它是异步的原因。GetImageAsync()
我会尽可能短地关闭 UI 。
如下GetImage_DelayRender
所示:
private async void GetImage_DelayRenderer(DataProviderRequest request)
{
var deferral = request.GetDeferral();
await Dispatcher.RunTask(async () => // RunTask() is an extension method - described in the original question below.
{
try
{
var bitmapStream = await GetImageAsync();
request.SetData(RandomAccessStreamReference.CreateFromStream(bitmapStream));
}
catch
{
}
});
deferral.Complete();
}
我想知道的是,实现上述调用的最正确方法是什么Dispatcher.RunTask()
(这是我的 hack 扩展方法)。
----- 开始原始消息 --------
假设我有以下任务:
private async Task SomeTask()
{
await Task.Delay(1000);
// Do some UI and other stuff that may also be async
}
编辑(澄清):我不想阻止用户界面。我要执行的任务(即使在示例中,如果您阅读它)不会阻塞 UI。我只希望任务在 UI 的上下文中运行,因为它是同步部分。
我想在 UI 线程上的代码上运行它作为异步操作。Dispatcher.RunXXX() 方法执行一个操作,这意味着它们将运行该操作并在完成时通知您。这还不够好。我需要整个任务在 UI 线程上运行(因为如果我从 UI 线程运行它就会执行),然后在完成后通知我。
我能想到的唯一方法是使用 Dispatcher.RunXXX() 方法来执行一个匿名委托,该委托将我的方法中的局部变量设置为任务,然后等待...
public async static Task RunTask(this CoreDispatcher dispatcher, Func<Task> taskGiver)
{
Task task = null;
await dispatcher.RunAsync(() => task = taskGiver());
await task;
}
这看起来非常丑陋。有更好的方法吗?
Edit2:伙计们-阅读此代码-如果我使用我拥有的 RunTask() hack 执行上面的第一个代码块,它不会阻塞 Task.Delay() 上的 UI...