线程不起作用,它冻结我的应用程序[重复]

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程不起作用,它冻结我的应用程序[重复]相关的知识,希望对你有一定的参考价值。

我有一个带有几个循环和数据库查询的函数,我想通过传递一个进度条来异步调用它来向用户显示进度。

当我调用线程程序挂起时,我甚至无法关闭

当我调用synchContext.Post(state => etlBusiness.LoadData(progressBar),null);它冻结了,将loadData的逻辑带到UI是不可行的,有许多方法被称为内部

 public partial class Home : Form
{
    public Home()
    {
        InitializeComponent();
        synchronizationContext = System.Threading.SynchronizationContext.Current;
    }

    private SynchronizationContext synchronizationContext;

    public SynchronizationContext context = SynchronizationContext.Current;

    public Thread _myThread = null;
    private void btnSend_Click(object sender, EventArgs e)
    {
        _myThread = new Thread(() => LoadData(synchronizationContext, progressBar1));

        _myThread.Start();

    }

    private void LoadData(System.Threading.SynchronizationContext synchContext, ProgressBar progressBar)
    {
        string filePath = tbPath.Text;
        ETLBusiness etlBusiness = new ETLBusiness(filePath);

        synchContext.Post(state => etlBusiness.LoadData(progressBar), null);
        _myThread.Abort();
    }

}
答案

你不需要使用Thread.Abort()SynchronizationContext甚至使用“异步”代码(我假设你指的是你不能调用的await / async,除非你的目标API实际上提供了真正的异步功能,请注意使用Task.Run不一样事情):WinForms具有内置功能,可以在Invoke / BeginInvoke方法的UI线程中运行代码。

对于进度报告,我不建议传递ProgressBar,因为这是一个脆弱的设计,意味着你的内部业务逻辑依赖于WinForms,这阻止你在WPF,ASP.NET或无头进程中使用它;相反,你可以有一个通过回调更新UI的私有方法,如下所示:

private ProgressBar progressBar;

public Home()
{
    this.InitializeComponent();
}

private void btnSend_Click( Object sender, EventArgs e )
{
    Task.Run( (Action)this.LoadData )
}

private void UpdateProgress( Float progress )
{
    if( this.InvokeRequired )
    {
        this.BeginInvoke( (Action<Float>)this.UpdateProgress, progress );
        return;
    }

    this.progressBar.Value = progress * this.progressBar.Maximum;
}

private void LoadData()
{
    ETLBusiness etlBusiness = new ETLBusiness(filePath);
    etlBusiness.LoadData( this.UpdateProgress ); // You'll need to replace its progressBar parameter with a callback to `this.UpdateProgress`.
}

你的ETLBusiness.LoadData方法应改为:

void LoadData( Action<Float> progressCallback );
另一答案

又是我。我在你上一篇文章中发表了评论。问题来自我的解决方案。发生的事情是你正在创建和启动一个线程,然后你用synchContext.Post()将ETLBusiness.LoadData()的逻辑发送回主线程。需要做的是以下两个选项之一:

  1. 将ETLBusiness.LoadData()的逻辑移动到Form.LoadData()(线程调用的方法),然后使用synchContext.Post(state => progressBar1.SetPercent())专门更新progressBar。
  2. 将线程移动到ETLBusiness类。并使用synchContext.Post(state => progressBar1.SetPercent())专门更新progressBar。

再次抱歉,此问题来自我之前发布的解决方案

以上是关于线程不起作用,它冻结我的应用程序[重复]的主要内容,如果未能解决你的问题,请参考以下文章

listview onclick toast在片段中不起作用[重复]

按钮在片段中不起作用

实时matplotlib图在循环中不起作用[重复]

Python 冻结的可执行文件在某些​​计算机上不起作用

IOS8:AVFoundation 相机冻结

替换或删除后台堆栈上现有片段的代码不起作用