【问题标题】:Separate thread from UI [closed]从 UI 中分离线程 [关闭]
【发布时间】:2016-03-26 09:02:48
【问题描述】:

我的程序有什么问题?我无法将执行线程与 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);
}

在第一个和第二个选项中,程序确实有效。但是在第一个和第二个选项中,用户无法访问 UI

【问题讨论】:

  • 您遇到什么错误或“无法到达”实际上是如何显示的?请提供准确的故障观察结果,而不是对您所看到的内容的一些解释!
  • 这是因为您将委托放在 UI 调度程序本身上,无论如何将其放回 UI 线程。您应该只在 UI 调度程序上委托 UI 任务,其余的可以在后台线程上运行。
  • 没有错误!程序运行良好!但是我不能移动窗口,或者点击任何按钮等等......
  • 罗希特大桶,谢谢!这肯定是解决方案
  • 您不应该手动运行线程。最好使用 async/await 模式,如果您运行旧的 Visual Studio(2013 之前)版本,最好使用 Task<T> 类型

标签: c# wpf multithreading mvvm dispatcher


【解决方案1】:

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

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

【讨论】:

  • 是的,就是这样。谢谢!
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-19
    • 1970-01-01
    • 1970-01-01
    • 2018-10-23
    • 1970-01-01
    相关资源
    最近更新 更多