gpt4 book ai didi

c# - 在 WPF 中,如何在另一个线程(另一个调度程序)上设置窗口的窗口所有者

转载 作者:行者123 更新时间:2023-11-30 16:19:51 25 4
gpt4 key购买 nike

我得到以下异常:InvalidOperationException:调用线程无法访问此对象,因为另一个线程拥有它。

当我尝试设置一个窗口的所有者时,该窗口是在所有者之外的另一个线程上构建的。

我知道我只能从适当的线程更新 UI 对象,但如果它来自另一个线程,为什么我不能只设置所有者?我可以用另一种方式做吗?我想让进度窗口成为唯一可以输入条目的窗口。

这是出现错误的代码部分:

    public partial class DlgProgress : Window
{
// ******************************************************************
private readonly DlgProgressModel _dlgProgressModel;

// ******************************************************************
public static DlgProgress CreateProgressBar(Window owner, DlgProgressModel dlgProgressModel)
{
DlgProgress dlgProgressWithProgressStatus = null;
var listDlgProgressWithProgressStatus = new List<DlgProgress>();
var manualResetEvent = new ManualResetEvent(false);
var workerThread = new ThreadEx(() => StartDlgProgress(owner, dlgProgressModel, manualResetEvent, listDlgProgressWithProgressStatus));
workerThread.Thread.SetApartmentState(ApartmentState.STA);
workerThread.Start();
manualResetEvent.WaitOne(10000);
if (listDlgProgressWithProgressStatus.Count > 0)
{
dlgProgressWithProgressStatus = listDlgProgressWithProgressStatus[0];
}

return dlgProgressWithProgressStatus;
}

// ******************************************************************
private static void StartDlgProgress(Window owner, DlgProgressModel progressModel, ManualResetEvent manualResetEvent, List<DlgProgress> listDlgProgressWithProgressStatus)
{
DlgProgress dlgProgress = new DlgProgress(owner, progressModel);
listDlgProgressWithProgressStatus.Add(dlgProgress);
dlgProgress.ShowDialog();
manualResetEvent.Set();
}

// ******************************************************************
private DlgProgress(Window owner, DlgProgressModel dlgProgressModel)
{
if (owner == null)
{
throw new ArgumentNullException("Owner cannot be null");
}

InitializeComponent();
this.Owner = owner; // Can't another threads owns it exception

最佳答案

上面的回答是正确的。但我会尽量总结:

     [DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);

public static void SetOwnerWindowMultithread(IntPtr windowHandleOwned, IntPtr intPtrOwner)
{
if (windowHandleOwned != IntPtr.Zero && intPtrOwner != IntPtr.Zero)
{
SetWindowLong(windowHandleOwned, GWL_HWNDPARENT, intPtrOwner.ToInt32());
}
}

获取 WPF 处理程序的代码:

 public static IntPtr GetHandler(Window window)
{
var interop = new WindowInteropHelper(window);
return interop.Handle;
}

请注意,窗口应在设置所有者调用之前初始化! (可以在 window.Loaded 或 window.SourceInitialized 事件中设置)

 var handler = User32.GetHandler(ownerForm);

var thread = new Thread(() =>
{
var window = new DialogHost();
popupKeyboardForm.Show();
SetOwnerWindowMultithread(GetHandler(popupKeyboardForm), handler);
Dispatcher.Run();
});

thread.IsBackground = true;
thread.Start();

也可以使用 SetParent。比你不需要转换处理程序:

[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

请注意,parent 和 owner 具有不同的含义。 Win32 window Owner vs window Parent?

关于c# - 在 WPF 中,如何在另一个线程(另一个调度程序)上设置窗口的窗口所有者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14896111/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com