【问题标题】:Positioning and maximizing a window that runs in a background task定位和最大化在后台任务中运行的窗口
【发布时间】:2014-12-04 08:51:20
【问题描述】:

好的,以下问题:

我在一台 PC 上的多达 10 个屏幕上有一些窗口。其中一些应该在后台任务中运行。它是一个 WPF 应用程序,但对于屏幕定位等,我使用了 WinForms 的某些部分。为此,我使用以下几行:

foreach (List<string> myStrings in Screen.AllScreens.Select(myScreen => _xml.GetScreenConfigs(i)))
{
  Thread newWindowThread = new Thread(() =>
  {
    Marketing myMarketing = new Marketing(i, myStrings[0]);
    myMarketing.Show();
    Dispatcher.Run();
  });
  newWindowThread.SetApartmentState(ApartmentState.STA);
  newWindowThread.IsBackground = true;
  newWindowThread.Start();
}

在这个窗口中,我使用以下内容来定位它:

[DllImport("user32.dll")]
private static extern IntPtr GetActiveWindow();
...
Left = Convert.ToInt32(screenArray[screenNumber].Bounds.Left);
Top = Convert.ToInt32(screenArray[screenNumber].Bounds.Top);
var active = GetActiveWindow();
var singleOrDefault = Application.Current.Windows.OfType<Window>()
  .SingleOrDefault(window => new WindowInteropHelper(window).Handle == active);
if (singleOrDefault == null) return;
singleOrDefault.Title = "Monitor" + screenNumber;
singleOrDefault.Name = "Monitor" + screenNumber;
singleOrDefault.WindowState = WindowState.Maximized;

但是当我到达“var singleOrDefault”行时,我收到一条错误消息,指出它无法更改对象 Application.Current.Windows,因为它由另一个线程拥有。 所以我的问题如下:

“我能做什么,在不同的线程中使用这个窗口并定位和最大化它?”

【问题讨论】:

  • 您确定需要多个 UI 线程吗?为什么不使用单个 UI 线程来显示后台操作的结果?
  • 是的,因为有一个 WebBrowser 控件运行多次,当我将它与 flash 一起使用时(而且我必须使用 flash,没有办法绕过它),在 3 个控件之后应用程序关闭当所有人都在同一个线程上运行时,它会跪下。
  • 正如我测试的那样,集合(Application.Current.Windows)只记录主线程上的窗口,您无法从中获取非主线程窗口。您是否试图从大量窗口中找到活动窗口并将其最大化?
  • 这正是我尝试过的。

标签: c# wpf multithreading winforms wpf-controls


【解决方案1】:

1) 你写了: 在这个窗口中,我使用以下内容来定位它: ... Application.Current.Windows.OfType&lt;Window&gt;..

您不能从任务内部对 Interop 进行操作。将它放在您的“主”窗口中。这就解释了线程异常。

2) 如果您在修改 UIElemetns 时不使用 windows 的调度程序,您可能会得到另一个线程异常。这就是“船长”的回答思路。 但是TitleNameWindowstate似乎不依赖于调度程序,因为这些应该是win32 props。

【讨论】:

  • 是的,但我怎样才能从 App.xaml.cs 中最大化 Marketing-Window?
  • 你不需要。您让我们知道:这一切都发生在“private void MarketingLoaded(object sender, RoutedEventArgs e)”中,为什么不使用发送者,因为加载的元素(“营销”窗口)是事件的发送者是很常见的?我不知道你的整体代码,所以从我这边,尝试类似:(sender as MarketingWIdow).WindowState = WindowState.Maximized
  • 我不想给这个帖子发垃圾邮件,所以请在此处查看对这个问题感兴趣的完整代码:pastebin.com/s2gPTVSh
  • 类 Marketing 不是 Window 的派生词。但是,您似乎与 Xaml 定义共享它是部分的。这看起来很奇怪。它应该派生自 Window 或任何 UserControl
【解决方案2】:

在设置或获取 UI 元素的属性时,您必须调用该元素的 Dispatcher 线程上的代码。

简而言之,试试这个:

Application.Current.Dispatcher.Invoke(() =>
{
    var singleOrDefault = Application.Current.Windows.OfType<Window>()
            .SingleOrDefault(window => new WindowInteropHelper(window).Handle == active);
    if (singleOrDefault == null) return;
    singleOrDefault.Title = "Monitor" + screenNumber;
    singleOrDefault.Name = "Monitor" + screenNumber;
    singleOrDefault.WindowState = WindowState.Maximized;
});

希望这会有所帮助...

【讨论】:

  • singleOrDefault 不能使用,因为在声明中我得到了错误。我什至不能使用这条线: var singleOrDefault = Application.Current.Windows.OfType() .SingleOrDefault(window => new WindowInteropHelper(window).Handle == active);
  • 然后将整个块包装在 Dispatcher.Invoke 从 var singleOrDefault = Application.Current.Windows.OfType 开始我编辑了我的答案
  • 我是这样写的,但没有任何进展。同样的错误: Dispatcher.Invoke(() =>{ var singleOrDefault = Application.Current.Windows.OfType() .SingleOrDefault(window => new WindowInteropHelper(window).Handle == active); ...} );
  • 您不能在声明 singleOrDefault 之前使用 singleOrDefault.Dispatcher.Invoke(()...(稍后会发生什么)。
  • 糟糕。你是对的。尝试 Application.Current.Dispatcher.Invoke 再次编辑我的答案:)
【解决方案3】:

好的,我(经过多次尝试和错误)对其中一个问题有了一点解决方案: 清除 Left=... 和 Top=... 之后的所有内容并填写 WindowState = WindowState.Maximized; 然后它最大化。 所以只剩下一个问题: 有时(不是每次启动)应用程序在“InitializeComponent();”行启动时崩溃在 Marketing.xaml.cs 中,然后有时一切正常。有时带有空引用异常,有时它表示已经有一个使用此名称声明的组件。 有人知道这可能是什么?必须对线程做点什么,因为这是我第一次遇到这些错误。

[编辑] 我找到了:我必须使用 lock(),所以现在我只需要了解如何使用它。有人有这些经验吗?

【讨论】:

    【解决方案4】:

    好的,有我搜索了近两天的答案:

    对于最大化: 清除 Left=... 和 Top=... 之后的所有内容并填写 WindowState = WindowState.Maximized;然后它最大化。

    对于异常错误: 在被调用的窗口中放置一个static readonly object _locker = new object(); 和一个 lock (_locker) { InitializeComponent(); }

    在窗口调用中。 感谢您的所有帮助,我会投票支持您的所有帖子,但我没有这样做的声誉。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-21
      • 2017-02-10
      相关资源
      最近更新 更多