LoginSignup
0
3

More than 5 years have passed since last update.

Dispatcherを作ってモデルを単一スレッドで実行したり画像をバックグラウンドでダウンロードしたり

Posted at

Dispatcherを作ってモデルを単一スレッドで実行したり画像をバックグラウンドでダウンロードしたり

ちゃんとした文献が見つからなかったから本当に問題ないかは知らない

Dispatcherを作って

App.xaml.cs
public partial class App : Application
{
    public static Dispatcher BackgroundDispatcher => CreateBackgroundDispatcherAsync().Result;
    static Task<Dispatcher> CreateBackgroundDispatcherAsync()
    {
        var tcs = new TaskCompletionSource<Dispatcher>();

        var th = new Thread(() => {
            var d = Dispatcher.CurrentDispatcher;
            tcs.SetResult(d);
            Current.Dispatcher.InvokeAsync(() => {
                Current.Exit += (sender, e) =>
                {
                    d.InvokeShutdown();
                };
            });
            Dispatcher.Run();
        });
        th.SetApartmentState(ApartmentState.STA);
        th.Start();

        return tcs.Task;
    }
}

モデルを単一スレッドで実行したり

モデルクラスを作って

Counter.cs
class Counter : DispatcherObject
{
    int _Count = 0;
    public int Count
    {
        get
        {
            VerifyAccess();
            return _Count;
        }
    }

    public void Add(int n)
    {
        VerifyAccess();
        _Count += n;
    }
}

何時も通りDispatcher経由で触る

async void btnCounter_Click(object sender, RoutedEventArgs e)
{
    var cnt = await App.BackgroundDispatcher.InvokeAsync(() => new Counter());

    await Task.WhenAll(Enumerable.Range(0, 10).Select(i => Task.Run(async () =>
    {
        foreach (var j in Enumerable.Range(0, 1000))
        {
            await cnt.Dispatcher.InvokeAsync(() => cnt.Add(1));
        }
    })));

    MessageBox.Show($"{ await cnt.Dispatcher.InvokeAsync(() => cnt.Count) }");
}

画像をバックグラウンドでダウンロードしたり

async void btnDownloadImage_Click(object sender, RoutedEventArgs e)
{
    imgMain.Source = await DownloadImageAsync(new Uri(txtUri.Text));
}

Task<BitmapImage> DownloadImageAsync(Uri uri)
{
    var tcs = new TaskCompletionSource<BitmapImage>();

    App.BackgroundDispatcher.InvokeAsync(() => {
        var bmp = new BitmapImage(uri);
        void handler(object sender, EventArgs e)
        {
            bmp.DownloadCompleted -= handler;
            bmp.Freeze();
            tcs.SetResult(bmp);
        }
        bmp.DownloadCompleted += handler;
    });

    return tcs.Task;
}

ソースコード

参考文献

0
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3