【问题标题】:Threading with IProgressDialog in c#在 C# 中使用 IProgressDialog 进行线程化
【发布时间】:2012-06-05 07:13:01
【问题描述】:

我想在我的 c# 应用程序中添加原生窗口 ProgressDialog。 为了更好地控制,我定义了一个 OnUserCancelled 事件。 从主窗体调用 ShowDialog() 后,ProgressDialog 类启动一个线程来检查原生 ProgressDialog 是否被取消。但问题是IProgressDialog属于主线程,无法从checker线程访问,错误严重:

无法将“WindowsDialogs.Invokes.Interfaces.IProgressDialogC”类型的 COM 对象转换为接口类型“WindowsDialogs.Invokes.Interfaces.IProgressDialog”。此操作失败,因为 IID 为“{EBBC7C04-315E-11D2-B62F-006097DF5BD4}”的接口的 COM 组件上的 QueryInterface 调用因以下错误而失败:不支持此类接口(HRESULT 异常:0x80004002 (E_NOINTERFACE)) .

我想知道有什么方法可以将我的命令调用到主类(例如 .net Form 中的 Invoke() 方法)。

注意:Timer 类也有同样的问题...

【问题讨论】:

  • 强制转换在主线程中不是问题,但在第二线程中可能是问题...

标签: c# multithreading invoke


【解决方案1】:

您应该对该 UI 主题中的进度对话框进行所有调用。 在 WPF 中我这样做:

Dispatcher.Invoke((Action)delegate()
{
    _progressDialog.SetProgress(percentComplete, 100);
});

对于 WinForms,我猜应该是 Control.Invoke: http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx

【讨论】:

    【解决方案2】:

    正如@karlas 所指出的,这是跨线程调用的问题。

    这是我使用内部计时器定期监控取消按钮状态的解决方案:

    private void _timerCallback(object state)
    {
        _parentForm.Invoke((Action) delegate {
            try
            {
                if (HasUserCancelled)
                {
                    Cancelled?.Invoke(this, EventArgs.Empty);
                }
            }
            catch (Exception)
            {
                // Swallow
            }
        });
    }
    

    _parentForm 字段在Show() 方法中设置如下:

    public void Show(IWin32Window parent){
        if (_parentForm == null)
            _parentForm = Form.ActiveForm;
        ...
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多