【发布时间】:2015-12-24 13:14:35
【问题描述】:
不幸的是,我不得不在与主应用程序不同的线程上触发此窗口。然后,每当我的 MakeWindow 类中的字符串输入 _html 发生更改时,我都会尝试对其进行更新。
现在我收到一条错误消息,说我无法执行此操作,因为我是从创建它的不同线程调用它。我怎样才能让它在这里工作?
有没有办法在窗口存在的同一线程上实现该事件侦听器?请记住,_html 将始终在主线程上设置和更新。想法?
谢谢!
我的课程:
namespace Windamow
{
public static class WebBrowserUtility
{
public static readonly DependencyProperty BindableSourceProperty =
DependencyProperty.RegisterAttached("BindableSource", typeof(string),
typeof(WebBrowserUtility), new UIPropertyMetadata(null,
BindableSourcePropertyChanged));
public static string GetBindableSource(DependencyObject obj)
{
return (string)obj.GetValue(BindableSourceProperty);
}
public static void SetBindableSource(DependencyObject obj, string value)
{
obj.SetValue(BindableSourceProperty, value);
}
public static void BindableSourcePropertyChanged(DependencyObject o,
DependencyPropertyChangedEventArgs e)
{
var webBrowser = (WebBrowser)o;
webBrowser.NavigateToString((string)e.NewValue);
}
}
public class Windamow
{
private DynamoWindow window;
public static string html;
internal void ThreadProc()
{
string appName = "";
try
{
appName = Path.GetFileName(System.Reflection.Assembly.GetEntryAssembly().Location);
const string IE_EMULATION = @"Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION";
using (var fbeKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(IE_EMULATION, true))
{
fbeKey.SetValue(appName, 9000, Microsoft.Win32.RegistryValueKind.DWord);
}
}
catch (Exception ex)
{
MessageBox.Show(appName + "\n" + ex.ToString(), "Unexpected error setting browser mode!");
}
window = new DynamoWindow();
window.ShowDialog();
}
internal Windamow()
{
Thread t = new Thread(ThreadProc);
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
/// <summary>
/// asd
/// </summary>
/// <param name="launch"></param>
/// <param name="_html"></param>
/// <returns></returns>
public static DynamoWindow MakeWindow(bool launch, string _html)
{
if (launch)
{
if (MyProject.Utility.WebBrowserUtility.IsWindowOpen<Window>("MainWindow"))
{
html = _html;
return null;
}
else
{
html = _html;
Windamow mow = new Windamow();
return mow.window;
}
}
else
{
return null;
}
}
}
}
xaml:
<Window x:Class="Windamow.DynamoWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
xmlns:ns="clr-namespace:Windamow"
Title="MainWindow"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<!--<WebBrowser x:Name="browser" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>-->
<WebBrowser x:Name="browser" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ns:WebBrowserUtility.BindableSource="{Binding ReportPage}"/>
</Grid>
xaml.cs:
namespace Windamow
{
/// <summary>
/// Interaction logic for DynamoWindow.xaml
/// </summary>
public partial class DynamoWindow : Window
{
public DynamoWindow()
{
InitializeComponent();
}
}
}
【问题讨论】:
-
你为什么要生成一个新线程只是为了打开另一个窗口,一个模态,无论如何?即使是STA。我不明白这一点,这可以说是糟糕的设计
-
@Roy 我正在从另一个应用程序运行它。这就是为什么我需要将它们保留在单独的线程上,因为我想让用户继续在主应用程序中工作。
-
@Roy 如果有办法通过主线程的非模式窗口来实现这一点,那么我非常乐意听取任何建议。提前致谢
-
@Konrad,我不确定一切。谁拥有 ReportPage 属性?它是从另一个线程修改的吗?如果是,您的问题的答案可能是将“webbrowser.Navigate”行更改为“webBrowser.Dispatcher.Invoke(() => { webBrowser.NavigateToString((string)e.NewValue);})”问候跨度>
标签: c# wpf multithreading xaml thread-safety