从UI分离线程

时间:2016-03-26 09:02:49

标签: c# wpf multithreading mvvm dispatcher

我的课程有什么问题?我无法将执行线程与UI分开。在执行线程期间无法访问UI。

这是我的viewmodel:

第一个选项:

// on button click:
this.CreateImageList();

private void CreateImageList()
{
    this.images.Clear();

    ThreadStart threadStart = delegate
    {
        this.dispatcher.BeginInvoke(new ThreadStart(delegate
        {
            foreach (var filePath in this.fileBuffer)
            {
                var result = new ImageObject(filePath);
                if (result.Image != null)
                {
                    this.images.Add(result);
                    this.dispatcher.Invoke(() => this.StatusText = filePath, DispatcherPriority.Render);
                }
            }

            this.RaisePropertyChanged("Images");
        }));
    };

    var thread = new Thread(threadStart);
    thread.IsBackground = true;
    thread.Start();
}

第二个选项:

// on button click:
this.CreateImageList();

private async void CreateImageList()
{
    await this.CreateImageListAsync();
}

private async Task CreateImageListAsync()
{
    this.images.Clear();
    var countTotal = this.fileBuffer.Count();
    var index = 0;

    await Task.Run(() => this.dispatcher.Invoke(
    (() =>
    {
        foreach (var filePath in this.fileBuffer)
        {
            var result = new ImageObject(filePath);
            if (result.Image != null)
            {
                this.images.Add(result);

                var percent = (index * 100) / countTotal;
                this.DoForce(() => this.StatusText = percent + "% " + filePath);
            }

            index++;
        }

        this.RaisePropertyChanged("Images");
    }), DispatcherPriority.SystemIdle));
}

public void DoForce(Action action)
{
    this.dispatcher.Invoke(DispatcherPriority.Render, action);
}

在第一个和第二个选项中,程序可以正常工作。但是在第一个和第二个选项中,用户无法访问UI

2 个答案:

答案 0 :(得分:4)

这是因为您将委托放在UI调度程序上,无论如何都会在UI线程上运行它(导致无响应的用户界面)

您应该仅在UI调度程序上委派UI任务,其余部分可以在后台线程上运行。

答案 1 :(得分:0)

我认为单独的线程(无论是后台线程还是UI线程)无权访问主线程(ProgressChanged除外)。我花了很多时间在这个问题上,我找不到从辅助线程永久访问主线程的方法。

我的UI线程解决方案是使用WndProc与扩展(lParam)值和/或注册表值一起在线程之间进行聊天。

使用后台工作线程我通过指向主线程的窗口属性指针访问progress事件中的主线程。您只能从BgWorker中的ProgressChanged事件访问主线程。