使用主窗体作为在不同线程上创建的新窗体的父窗体

发布于 2024-12-26 06:59:09 字数 698 浏览 1 评论 0原文

我有一个运行BackgroundWorker 线程的主窗体。 当工作人员运行时,我“冻结”主窗体并等待它完成,同时显示其进度。

在其中一种场景中,工作人员可以显示 OpenFileDialog 供用户选择文件。 我使用第三个线程来运行 OpenFileDialog 并将其 ApartmentState 设置为 STA,因为 OpenFileDialog 需要它(如果我不这样做,则会引发异常)并且工作器 ApartmentState 是 MTA。

问题是我想将主窗体作为参数传递给 OpenFileDialog 线程,以便在调用 OpenFileDialog.ShowDialog 时可以使用它。 像这样:

public void ThreadProcShowDialog(object param)
{
    Form parent = (Form)param;
    dialog.ShowDialog(parent);
}

当然,ShowDialog 会抛出:

跨线程操作无效:从 a 访问控制“表单” 除了创建它的线程之外的线程。

我怎样才能以线程安全的方式做到这一点?

这样做的目的是 OpenFileDialog 将在 STA 线程中运行,同时阻止主窗体在其上显示(阻止用户单击下面的窗体,从而隐藏 OpenFileDialog)。

谢谢

I have a main form that runs a BackgroundWorker thread.
While the worker is running I "freeze" the main form and wait for it to finish while showing its progress.

In one on the scenarios the worker can display an OpenFileDialog for the user to select a file.
I use a third thread to run the OpenFileDialog and set it's ApartmentState to STA because the OpenFileDialog demands it (throws exception if I don't do it) and the worker ApartmentState is MTA.

The problem is that I want to pass to the OpenFileDialog thread the main form as a parameter so it can be used when calling OpenFileDialog.ShowDialog.
Something like this:

public void ThreadProcShowDialog(object param)
{
    Form parent = (Form)param;
    dialog.ShowDialog(parent);
}

Of course, ShowDialog throws:

Cross-thread operation not valid: Control 'Form' accessed from a
thread other than the thread it was created on.

How can I do this in a thread safe manner?

The object of this is that the OpenFileDialog will run in a STA thread while blocking the main form from displaying over it (block the user from clicking the form below thus hiding the OpenFileDialog).

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

毁虫ゝ 2025-01-02 06:59:09

找到了!

与我一起工作的一位程序员同事提出了一个实际有效的简单解决方案。
不必在第三个线程上运行 OpenFileDialog,只需在主窗体(启动工作线程的窗体)上运行它。

它看起来像这样:

//Code inside worker method
OpenFileDialog dialog= new OpenFileDialog();
DialogResult result = DialogResult.None;

Invoke(new MethodInvoker(delegate() { result = dialog.ShowDialog(this); }));
if (result == DialogResult.OK)
{
    ...
}

这样我阻止主窗体被单击,并且 OpenFileDialog 在 STA 线程中运行。

并且认为解决这个问题的是一名 C++ 程序员;-)

我希望这对某人有帮助......

Found it!

A fellow programmer working with me suggested a simple solution that actually worked.
Instead of running the OpenFileDialog on a third thread just run it on the main form (the one that started the worker thread.

It looks like this:

//Code inside worker method
OpenFileDialog dialog= new OpenFileDialog();
DialogResult result = DialogResult.None;

Invoke(new MethodInvoker(delegate() { result = dialog.ShowDialog(this); }));
if (result == DialogResult.OK)
{
    ...
}

This way I block the main form from being clicked and the OpenFileDialog runs in a STA thread.

And to think the one that solved it is a C++ programmer. ;-)

I hope this will be helpful to someone...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文