簡體   English   中英

WPF MVVM 和 TPL 數據流中的進度條

[英]Progress bar in WPF MVVM and TPL dataflow

我在遵循 MVVM 模式的 WPF 應用程序中使用 TPL 數據流。 我有一個TransformBlock<object,object>和一個ActionBlock<object> ,我像這樣鏈接它們:

transformBlock.LinkTo(notificationBlock);

ActionBlock<object>應該使用當前進度更新我視圖中的進度條,但 UI 似乎被凍結,並且只有在一切都完成處理后才會更新。

我的CurrentProgress屬性如下所示:

private double _CurrentProgress;

public double CurrentProgress
{
    get { return _CurrentProgress; }
    set
    {
        _CurrentProgress = value;
        RaisePropertyChanged("CurrentProgress");
    }
}

我將它綁定到我的視圖,如下所示:

<ProgressBar Value="{Binding CurrentProgress, Mode=OneWay}" Name="uxProgressBar"/>

我錯過了什么嗎? 為什么 TPL 會阻塞 UI 線程?

編輯

這就是我實例化 TPL 的方式:

foreach(var myObj in ObjList)
{
    transformBlock.Post(myObj);
}

轉換塊:

TransformBlock<object, object>(
temp =>
{
    var response = ProcessRecord(temp);
    return response.Status;
},
new ExecutionDataflowBlockOptions
{
    MaxDegreeOfParallelism =20
});

動作塊:

ActionBlock<object>(
temp =>
{
    CurrentProgress = (double)temp.RecordNumber/(double)TotalRecords;
},
new ExecutionDataflowBlockOptions
{
    TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext()
});

更新

TransformBlock中調用的 web 服務是一個遺留 (asmx) web 服務,它沒有被稱為Async 解決此問題后,其他一切正常,無需使用Dispatcher或任何其他建議的解決方案。

從評論之一到問題,似乎 WPF 確實支持從另一個線程發布到 UI 線程。 不過,我還沒有找到任何關於此的官方文檔。

嘗試使用“SendAsync”將您的代碼發布到 TransformBlock:

foreach (var myObj in ObjList)
{
   await transformBlock.SendAsync(myObj);
}

首先,您的ActionBlock不必直接更改CurrentProgress屬性。

原因是RaisePropertyChanged函數會直接運行ProgressBar對象的代碼。 這是不允許的,因為它是 UIThread 擁有的對象。

ActionBlock在他自己的線程中運行,他需要將 progressBar 更新順序發布到 UI 線程(通過使用Dispatcher.BeginInvoke ):

ActionBlock<object>(
temp =>
{
    double progress = (double)temp.RecordNumber/(double)TotalRecords;
    Dispatcher.BeginInvoke((Action)(() =>
    {
        CurrentProgress = progress;
    }));
},
new ExecutionDataflowBlockOptions
{
    TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext()
});

你必須改變這第一件事,才能做出你想要的。

其次(如果這不會改變任何東西),您必須檢查您的 UI 線程是否沒有等待TransformBlock的完成。 如果您的ICommand (例如,如果您從按鈕調用它)不是 ASync 並執行以下操作:

transformBlock.Completion.Wait();

不行。 因為你的 UIThread 會等待你的處理結束,直到結束才會接之前的progressBar更新命令。

祝你好運 ! 如果它總是不起作用,請發布新的詳細信息。

您應該使用Dispatcher通知 UI 線程您要從后台進程更新綁定值。

這是一篇解釋文章的鏈接:

http://msdn.microsoft.com/en-us/magazine/cc163328.aspx

http://msdn.microsoft.com/en-us/library/vstudio/system.windows.threading.dispatcher

我將整理一個類似的代碼示例並很快更新此響應。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM