我想在我的c#应用程序中添加原生窗口 ProgressDialog 。 为了更好地控制,我定义了一个 OnUserCancled 事件。 在 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表格中的 Invoke()方法。)
注意:Timer类有同样的问题......
答案 0 :(得分:0)
您应该对该UI中的进度对话框进行所有调用。 在WPF中我做:
Dispatcher.Invoke((Action)delegate()
{
_progressDialog.SetProgress(percentComplete, 100);
});
对于WinForms,我猜这将是Control.Invoke: http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx
答案 1 :(得分:0)
正如@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;
...
}