Jam*_*s T 13 c# multithreading winforms
现在我有C#代码在不同的线程中生成一个新窗口,这是有效的,但是一旦新生成的窗口打开,它就会关闭并且线程结束.我怎样才能使这个新生成的窗口可以从第一个线程关闭?
这是产卵目前如何运作的"树":
主线程 -
在主线程中使用一个函数在另一个线程中启动另一个函数来打开w窗口,导致窗口使用该线程.
基本上我只想让每个窗口都有自己的线程.并能够从第一个窗口线程控制生成的辅助窗口.
Rom*_*kov 30
我打赌你正在做的是这样的:
new Thread(() => new TestForm().Show()).Start();
Run Code Online (Sandbox Code Playgroud)
因为这会使窗口立即消失,就像你描述的那样.
试试这个:
new Thread(() => new TestForm().ShowDialog()).Start();
Run Code Online (Sandbox Code Playgroud)
ShowDialog旋转自己的消息泵,仅在窗口关闭时返回.
Ter*_*ver 14
这只是一个简单的例子.它比我写的第一个更强大.它通过使用p/invoke消除了现有的竞争条件.
更新 Still仍有竞争条件.这个应该是完美的.
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
class MainUIThreadForm : Form
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainUIThreadForm());
}
private IntPtr secondThreadFormHandle;
public MainUIThreadForm()
{
Text = "First UI";
Button button;
Controls.Add(button = new Button { Name = "Start", Text = "Start second UI thread", AutoSize = true, Location = new Point(10, 10) });
button.Click += (s, e) =>
{
if (secondThreadFormHandle == IntPtr.Zero)
{
Form form = new Form
{
Text = "Second UI",
Location = new Point(Right, Top),
StartPosition = FormStartPosition.Manual,
};
form.HandleCreated += SecondFormHandleCreated;
form.HandleDestroyed += SecondFormHandleDestroyed;
form.RunInNewThread(false);
}
};
Controls.Add(button = new Button { Name = "Stop", Text = "Stop second UI thread", AutoSize = true, Location = new Point(10, 40), Enabled = false });
button.Click += (s, e) =>
{
if (secondThreadFormHandle != IntPtr.Zero)
PostMessage(secondThreadFormHandle, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
};
}
void EnableStopButton(bool enabled)
{
if (InvokeRequired)
BeginInvoke((Action)(() => EnableStopButton(enabled)));
else
{
Control stopButton = Controls["Stop"];
if (stopButton != null)
stopButton.Enabled = enabled;
}
}
void SecondFormHandleCreated(object sender, EventArgs e)
{
Control second = sender as Control;
secondThreadFormHandle = second.Handle;
second.HandleCreated -= SecondFormHandleCreated;
EnableStopButton(true);
}
void SecondFormHandleDestroyed(object sender, EventArgs e)
{
Control second = sender as Control;
secondThreadFormHandle = IntPtr.Zero;
second.HandleDestroyed -= SecondFormHandleDestroyed;
EnableStopButton(false);
}
const int WM_CLOSE = 0x0010;
[DllImport("User32.dll")]
extern static IntPtr PostMessage(IntPtr hWnd, int message, IntPtr wParam, IntPtr lParam);
}
internal static class FormExtensions
{
private static void ApplicationRunProc(object state)
{
Application.Run(state as Form);
}
public static void RunInNewThread(this Form form, bool isBackground)
{
if (form == null)
throw new ArgumentNullException("form");
if (form.IsHandleCreated)
throw new InvalidOperationException("Form is already running.");
Thread thread = new Thread(ApplicationRunProc);
thread.SetApartmentState(ApartmentState.STA);
thread.IsBackground = isBackground;
thread.Start(form);
}
}
Run Code Online (Sandbox Code Playgroud)
这是后人的第一个例子:
using System;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
class MainUIThreadForm : Form
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainUIThreadForm());
}
SecondUIThreadForm secondThreadForm;
public MainUIThreadForm()
{
Text = "First UI";
Button button;
Controls.Add(button = new Button { Text = "Start second UI thread", AutoSize = true, Location = new Point(10, 10) });
button.Click += (s, e) =>
{
if (secondThreadForm == null || !secondThreadForm.IsHandleCreated)
secondThreadForm = SecondUIThreadForm.Create();
};
Controls.Add(button = new Button { Text = "Stop second UI thread", AutoSize = true, Location = new Point(10, 40) });
button.Click += (s, e) =>
{
if (secondThreadForm != null && secondThreadForm.IsHandleCreated)
secondThreadForm.Invoke((Action)(() => secondThreadForm.Close()));
};
}
}
class SecondUIThreadForm : Form
{
static void Main2(object state)
{
Application.Run((Form)state);
}
public static SecondUIThreadForm Create()
{
SecondUIThreadForm form = new SecondUIThreadForm();
Thread thread = new Thread(Main2);
thread.SetApartmentState(ApartmentState.STA);
thread.Start(form);
return form;
}
public SecondUIThreadForm()
{
Text = "Second UI";
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
62184 次 |
| 最近记录: |