以下元のメッセージ。なぜ私がこれを求めているのか、より詳細に説明してみましょう。
共有チャーム リクエストをリッスンするページがあります。
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()
上記の呼び出しを実現する最も正しい方法は何ですか (これは私のハック拡張メソッドです)。
----- オリジナルメッセージの開始 -------
次のタスクがあるとします。
private async Task SomeTask()
{
await Task.Delay(1000);
// Do some UI and other stuff that may also be async
}
編集 (明確化): UI をブロックしたくありません。私が実行したいタスクは(例を読んでも)UIをブロックしません。同期部分の UI のコンテキストでタスクを実行したいだけです。
これを UI スレッドのコードで非同期操作として実行したいと考えています。Dispatcher.RunXXX() メソッドはアクションを実行します。つまり、アクションを実行し、完了したら通知します。それは十分ではありません。タスク全体を UI スレッドで実行する必要があり (UI スレッドから実行した場合は実行されたはずです)、完了したら通知を受け取る必要があります。
私が考えることができる唯一の方法は、Dispatcher.RunXXX() メソッドを使用して、メソッド内のローカル変数をタスクに設定し、それを待機する anon デリゲートを実行することです...
public async static Task RunTask(this CoreDispatcher dispatcher, Func<Task> taskGiver)
{
Task task = null;
await dispatcher.RunAsync(() => task = taskGiver());
await task;
}
これはかなり醜いように見えます。それを行うより良い方法はありますか?
Edit2:みんな-このコードを読んでください-私が持っているRunTask()ハックを使用して上記の最初のコードブロックを実行すると、Task.Delay()のUIをブロックしません...