线程不起作用,它冻结了我的应用程序

时间:2018-03-01 20:00:31

标签: c# asynchronous

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

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

当我调用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();
    }

}

2 个答案:

答案 0 :(得分:0)

您不需要使用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 );

答案 1 :(得分:-1)

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

  1. 将ETLBusiness.LoadData()的逻辑移动到Form.LoadData()(线程调用的方法)中,然后使用synchContext.Post(state =&gt; progressBar1.SetPercent())专门更新progressBar。
  2. 将线程移至ETLBusiness类。并使用synchContext.Post(state =&gt; progressBar1.SetPercent())专门更新progressBar。
  3. 再次抱歉,此问题来自我之前发布的解决方案