将线程与 UI 分开

Separate thread from UI

我的程序有什么问题?我无法将正在执行的线程与 UI 分开。 UI 在线程执行期间无法到达。

这是我的视图模型:

第一个选项:

// 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);
}

在第一个和第二个选项中,该程序都有效。但是在第一个和第二个选项中,User

无法达到 UI

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

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

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

我对 UI 线程的解决方案是使用 WndProc 与扩展 (lParam) 值 and/or 注册表值一致地在线程之间聊天。

对于后台工作线程,我通过 window 属性 指向主线程的指针访问了进度事件中的主线程。您只能从 BgWorker 中的 ProgressChanged 事件访问主线程。