在更新UI时使用多个线程

时间:2015-03-16 23:07:33

标签: c# .net wpf multithreading

背景资料:

我正在为我的项目创建批处理编码器。它是这样的:(我只需要在每个项目中添加取消按钮并替换占位符)

Batch Encoder

对于添加的每个项目,线程/任务应处理给定的信息(图像)并作为编码图像保存在磁盘上。

我习惯使用delegatedelegateObject.BeginInvoke(...),但我只使用static方法中的delegate次调用更新了用户界面。

问题:

我使用WinForms执行此操作,而不是使用动态的项目列表。 另外,我不熟悉从UI中取消线程/任务。

问题:

我需要一点努力才能找到解决这个问题的最佳方法。

如何管理多个并行操作并更新UI?

2 个答案:

答案 0 :(得分:1)

您是否看过使用取消令牌?有点像:

private CancellationTokenSource _cts;

private async void start_Click(object sender, EventArgs e)
{
    _cts = new CancellationTokenSource();
    var token = _cts.Token;
    try
    {
        await Task.Run(() =>
        {
           // Your encoding process
        });
    }
    catch (OperationCanceledException)
    {
       // Handle cancellation
    }
}

private void stop_Click(object sender, EventArgs e)
{
    if (_cts != null)
        _cts.Cancel();
}

答案 1 :(得分:0)

这是工作代码。它将并排运行编​​码过程,如果使用InternalUpdate的正确ID调用Task方法,则会更新UI。

工作代码:

int a = 0;
var context = TaskScheduler.FromCurrentSynchronizationContext();
var task = new Task(() =>
{
    Encode(listFrames, a);
},
_cancellationToken.Token);

//Unique ID.
a = task.Id;

//Adds the item to the list.
var encoderItem = new EncoderListViewItem
{
    Image = (UIElement)Resources["Image"],
    Text = "Starting",
    Percentage = 0,
    Id = a
};

EncodingListBox.Items.Add(encoderItem);

_taskList.Add(task);
_taskList.Last().Start();

更新每个项目:

private void InternalUpdate(int id, double percentagem, string status)
{
    this.Dispatcher.Invoke(() =>
    {
        var item = EncodingListBox.Items.Cast<EncoderListViewItem>().FirstOrDefault(x => x.Id == id);

        if (item != null)
        {
            item.Percentage = percentagem;
            item.Text = status;
        }
     });
}