WPF异步任务锁定UI

Swi*_*fty 0 wpf async-await

我知道我错过了一些愚蠢的东西,"StartProcess"方法使得用户界面没有反应,没有大量的谷歌搜索和教程让我得到答案.

这是我的代码:

    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);
    }
Run Code Online (Sandbox Code Playgroud)

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

Sri*_*vel 6

好吧,你要求TPL调用FuncUI线程,它服从你的话.

在StartNew中,您传递uiScheduleras TaskScheduler,因此任务将排队到DispatcherUI线程将调用.

如果您不想在UI线程中执行然后使用TaskScheduler.Default,那么您无法txtBlock.Text在内部更新Func.您需要封送对UI线程的调用,或者只是设置之前的txtBlock.Text外部.FuncStartNew

Task.Run如果你在.Net 4.5,总是更喜欢,请注意StartNew是危险的.

有几点需要注意:

  • 请注意,您根本没有利用此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
    }
}
Run Code Online (Sandbox Code Playgroud)