调用synchrounous方法异步阻塞主线程

时间:2017-06-30 13:35:09

标签: c# multithreading asynchronous timer callback

我有一个使用frm.ShowDialog()调用的表单。

此表单异步调用同步方法。然后,一旦异步操作完成,就会执行其关联的回调。在回调中,我创建了一个计时器并启动它。

private System.Threading.Timer _timer;

public delegate int GetPriceDelegate(Person person, out string resultMsg);
int GetPrice(Person person, out string resultMsg);


private void FrmPrices_Load(object sender, System.EventArgs e)
{       
            AsyncCallback callback = new AsyncCallback(PriceCallback);
            GetPriceDelegate handler = new GetPriceDelegate(Commons.GetPrice);
            handler.BeginInvoke(person, out resultMsg, callback, null);
}

private void PriceCallback(IAsyncResult result)
{
            GetPriceDelegate handler = (GetPriceDelegate) ((AsyncResult) result).AsyncDelegate;

            try
            {
                string resultMsg;
                int rs = handler.EndInvoke(out resultMsg, result);

                // Do some stuff with returned rs.

                // Then create timer and start it
            System.Threading.TimerCallback callback = new System.Threading.TimerCallback(Timer_Callback);
            _timer = new System.Threading.Timer(callback, null, 10000, System.Threading.Timeout.Infinite);                

            }
            catch (Exception ex)
            {
                 // do something
            }
}


private void Timer_Callback(object state)
{
    this.Close();
}    

我的问题是异步调用同步方法似乎阻止了主线程。异步调用正确完成并执行其回调。计时器已创建并正确启动,但是当计时器过去后,执行此操作。关闭()所有表单都被卡住(没有响应),它会挂起。

异步调用的同步方法包括对Web服务的调用。

发生了什么事?无法在异步回调方法中创建和启动计时器?

我知道问题是在异步回调中创建和启动计时器(当它完成时)因为我试图在表单加载中创建和启动计时器并注释关于异步调用的所有代码并且它工作正常,表单已关闭确定

那么如何解决这个问题?我需要在异步调用完成后创建并启动计时器,在调用endInvoke之后,当计时器结束时,它正确关闭表单。任何解决方案?

更新

我在下面做了但没有成功:

private void Timer_Callback(object state)
{
        if (this.InvokeRequired)
        {
            Invoke(new TimerCallbackDelegate(Timer_Callback), new object[]{ state });
        }
        else
        {               this._timer.Change(System.Threading.Timeout.Infinite,System.Threading.Timeout.Infinite);
            this._timer.Dispose();

            this.Close();
        }       
    }

1 个答案:

答案 0 :(得分:-1)

@ user1624552:看起来您正尝试使用Invoke对UI进行同步调用,而不是尝试使用BeginInvoke。

private void Timer_Callback(object state)
{
    if (this.InvokeRequired)
    {
        BeginInvoke(new TimerCallbackDelegate(Timer_Callback), new object[]{ 
        state });
    }
    else
    {     
      this._timer.Change(System.Threading.Timeout.Infinite,
      System.Threading.Timeout.I
  nfinite);
        this._timer.Dispose();

        this.Close();
    }       
}