WPF异步任务锁定UI

时间:2014-09-10 15:15:07

标签: wpf async-await

我知道我错过了一些愚蠢的东西," StartProcess"方法是让UI无法响应,没有任何谷歌搜索和教程让我得到答案。

这是我的代码:

    public MainWindow()
    {
        InitializeComponent();
        txtBlock.Text = "Testing";
        Initialize();
    }

    public void Initialize()
    {
        uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();

        StartProcess();
    }

    async void StartProcess()
    {
         Task<int> result = Task.Factory.StartNew(() =>
        {
            txtBlock.Text += ("\n starting updater");
            while (true)
            {
                Thread.Sleep(3000);
            }
            return 0;
        }, CancellationToken.None, TaskCreationOptions.LongRunning, uiScheduler);
    }

一些背景知识:我正构建一个必须每隔5分钟轮询数据库的应用程序,并使用用户的待办事项列表更新UI,因此是while(true)循环。该应用程序必须在其整个生命周期内连续轮询数据库。

1 个答案:

答案 0 :(得分:6)

好吧,你要求TPL调用UI线程中的Func,它会听从你的话。

在StartNew中,您将uiScheduler作为TaskScheduler传递,因此任务将排队到Dispatcher,这将由UI线程调用。

如果您不想在UI线程中执行,请使用TaskScheduler.Default,这样做无法更新txtBlock.Text内的Func。您需要封送对UI线程的调用,或者只需在txtBlock.Text之前将Func设置在StartNew之外。

如果你在.Net 4.5中,总是更喜欢Task.Run,请注意StartNew is dangerous

需要注意的事项:

  • 请注意,您根本没有利用async功能。没有 await关键字方法根本不是异步。你不需要 async关键字(事实上你会收到编译器警告,请付款 注意编译器说的内容。)
  • 避免异步void方法(事件处理程序除外),如果您不需要任何返回值,请始终使用async Task,以便您可以在调用者中等待它或附加continuation等等。

更新以添加一些代码:

async Task StartProcess()
{
    while (true)
    {
        var result = await Task.Run(()=> MethodWhichCallsDBAndReturnsSomething());
        txtBlock.Text = result.ToString();//Use result and update UI
        await Task.Delay(5 * 60 * 1000);//await 5 mins
    }
}