我有要求,我需要在股票代号上显示带有一些 GIF 图像和 jpeg 或媒体元素的平滑滚动文本。但是,由于这涉及主 UI 线程的大量 CPU 周期,因此我计划在另一个具有调度程序的线程上创建代码控件,然后在窗体上托管此代码。但是,我收到一个跨线程异常,线程无法访问该控件,因为另一个线程拥有它。
我在Delphi中做了类似的事情,其中我用SetWindowParent()设置了股票代父级;
我的代码如下
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
TickerControlContainer loclContainer = new TickerControlContainer(this);
}
}
public class TickerControlContainer
{
private MainWindow f_Window;
private void CreateControl()
{
TickerControl loclControl = new TickerControl();
loclControl.InitializeComponent();
f_Window.Dispatcher.Invoke((MethodInvoker)delegate { AddControl(loclControl); });
}
private void AddControl(TickerControl piclControl)
{
f_Window.Content = piclControl;
**// exception occurs**
}
public TickerControlContainer(MainWindow piclWindow)
{
f_Window = piclWindow;
ManualResetEvent loclResetEvent = new ManualResetEvent(false);
Dispatcher loclDispatcher = null;
Thread th1 = new Thread(new ThreadStart(() =>
{
loclDispatcher = Dispatcher.CurrentDispatcher;
loclResetEvent.Set();
Dispatcher.Run();
}));
th1.SetApartmentState(ApartmentState.STA);
th1.Start();
loclResetEvent.WaitOne();
loclDispatcher.BeginInvoke((MethodInvoker)delegate { CreateControl(); });
}
}
我是否需要在我的表单上放置内容控件或其他内容,而不是设置为表单的内容。
这只是我正在尝试做的一个示例。请帮忙。
WPF/.NET 中只有一个 UI 线程(尽管我认为不同的窗口可以在不同的线程上运行),所以我真的不认为有一种简单的方法来执行您在这里尝试做的事情。
是动画占用了大量CPU,还是除了动画之外还进行了大量处理? 如果是这样,我会将计算卸载到后台线程,然后在完成后将其调用到 UI 线程。
我能够在主窗口上托管在另一个线程上创建的控件,但在创建控件之前,该窗口必须至少显示一次。
using...
namespace WpfMultiDispatcherUpdates
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void btnCreateControl_Click(object sender, RoutedEventArgs e)
{
TickerControlContainer loclContainer = new TickerControlContainer(this);
}
}
public class TickerControlContainer
{
private MainWindow f_Window;
[DllImport("user32.dll", SetLastError=false, ExactSpelling=false)]
private static extern IntPtr SetParent(IntPtr hwndChild, IntPtr hwndParent);
private void CreateControl(HwndSource piclSource)
{
TickerControl loclControl = new TickerControl();
loclControl.InitializeComponent();
Window loclHostWindow = new Window();
loclHostWindow.WindowStyle = WindowStyle.None;
loclHostWindow.WindowState = WindowState.Normal;
loclHostWindow.Left = 0;
loclHostWindow.Top = 0;
loclHostWindow.ShowInTaskbar = false;
loclHostWindow.Content = loclControl;
loclHostWindow.ShowActivated = true;
loclControl.Height = 200;
loclControl.Width = (double)f_Window.Dispatcher.Invoke(new Func<double>(() => { return f_Window.Width; }));
piclSource.SizeToContent = SizeToContent.WidthAndHeight;
loclHostWindow.SizeToContent = SizeToContent.WidthAndHeight;
loclHostWindow.Show();
SetParent(new WindowInteropHelper(loclHostWindow).Handle, piclSource.Handle);
}
private void AddControl(TickerControl piclControl)
{
f_Window.Content = new ContentControl() { Content = piclControl };
}
public TickerControlContainer(MainWindow piclWindow)
{
f_Window = piclWindow;
ManualResetEvent loclResetEvent = new ManualResetEvent(false);
Dispatcher loclDispatcher = null;
Thread th1 = new Thread(new ThreadStart(() =>
{
loclDispatcher = Dispatcher.CurrentDispatcher;
loclResetEvent.Set();
try
{
Dispatcher.Run();
}
catch (Exception E)
{
System.Windows.MessageBox.Show(E.Message);
}
}));
th1.SetApartmentState(ApartmentState.STA);
th1.Start();
loclResetEvent.WaitOne();
try
{
HwndSourceParameters loclSourceParams = new HwndSourceParameters();
loclSourceParams.WindowStyle = 0x10000000 | 0x40000000;
loclSourceParams.SetSize((int)piclWindow.Width, 200);
loclSourceParams.SetPosition(0, 20);
loclSourceParams.UsesPerPixelOpacity = true;
loclSourceParams.ParentWindow = new WindowInteropHelper(piclWindow).Handle;
HwndSource loclSource = new HwndSource(loclSourceParams);
loclSource.CompositionTarget.BackgroundColor = Colors.Transparent;
loclDispatcher.BeginInvoke((MethodInvoker)delegate { CreateControl(loclSource); });
}
catch (Exception E)
{
System.Windows.MessageBox.Show(E.Message);
}
}
}
}
但是,我需要添加 调整大小 事件并在主窗口高度和宽度更改时调整控件大小。这些值是硬编码的,用于测试目的。现在,子控件上的绘图不会影响我的主窗口,但控制子控件的复杂性更高。
宿主在我们承载此线程控件的区域中不应有任何其他子控件。