C# 如何为位于dll内部而不是WPF应用程序内部的WPF窗体创建单独的STA线程?

C# 如何为位于dll内部而不是WPF应用程序内部的WPF窗体创建单独的STA线程?,c#,.net,wpf,sta,C#,.net,Wpf,Sta,我有一个包含WPF表单的dll。这个dll将被另一个WPF应用程序调用,不幸的是,我无法访问它。问题是在我的WPF表单中没有要放置的主方法 [STAThread] static void Main() { //... } 异常就在我的类的构造函数上抛出。在这种情况下,我如何避开STA问题。同样,这不是WPF应用程序,而是放在dll内部的WPF表单 namespace VisualScannerTest { /// <summary> /// Interact

我有一个包含WPF表单的dll。这个dll将被另一个WPF应用程序调用,不幸的是,我无法访问它。问题是在我的WPF表单中没有要放置的主方法

[STAThread]
static void Main() {
    //...
}
异常就在我的类的构造函数上抛出。在这种情况下,我如何避开STA问题。同样,这不是WPF应用程序,而是放在dll内部的WPF表单

namespace VisualScannerTest
{
    /// <summary>
    /// Interaction logic for VisualScanner.xaml
    /// </summary>
    public partial class VisualScanner :Window,IPeripheral<VisualScanner.VisualScannerSettings>
    {
        private VisualScannerSettings _settings;
        private readonly IEventManager _eventManager;


        public VisualScanner(IEventManager eventManager):base()
        {
            InitializeComponent();
            _eventManager = eventManager;
        }


        private void SubmitButton_Click(object sender, RoutedEventArgs e)
        {
             string input = InpuTextBox.Text;
             InpuTextBox.Text = string.Empty;
            if (!string.IsNullOrWhiteSpace(input))
            {
                _eventManager.GetEvent<PeripheralEvent>().Publish(new PeripheralEventData {RawData = input});
            }

        }


        public void Initialize(VisualScannerSettings settings)
        {
            _settings = settings;
        }

        public IEnumerable<string> RegisterImpulses()
        {
            yield break;
        }

        public string Type
        {
            get { return GetType().FullName; }
        }
         public sealed class VisualScannerSettings:PeripheralSettings
        {
            public string Data { get; set; }   
        }
    }
}
命名空间VisualScannerTest
{
/// 
///VisualScanner.xaml的交互逻辑
/// 
公共部分类VisualScanner:Window、IPeripheral
{
专用VisualScannerSettings\u设置;
私有只读IEventManager\u eventManager;
公共VisualScanner(IEventManager事件管理器):base()
{
初始化组件();
_eventManager=eventManager;
}
私有无效提交按钮单击(对象发送者,路由目标)
{
字符串输入=InpuTextBox.Text;
InpuTextBox.Text=string.Empty;
如果(!string.IsNullOrWhiteSpace(输入))
{
_eventManager.GetEvent().Publish(新的外围设备eventdata{RawData=input});
}
}
公共无效初始化(VisualScannerSettings设置)
{
_设置=设置;
}
公共IEnumerable注册表脉冲()
{
屈服断裂;
}
公共字符串类型
{
获取{return GetType().FullName;}
}
公共密封类VisualScanner设置:外围设备设置
{
公共字符串数据{get;set;}
}
}
}

我首先建议您将dll转换为另一个具有自己线程的WPF应用程序,然后您需要一种不同的方式与之通信,例如使用两个应用程序都引用的另一个dll,或者使用一些方法,例如TCP套接字

或者,您可以尝试在
dll
中公开消费者的STA线程上需要调用的内容。因此,您可以将其称为应用程序,例如:

CreateForm();
比如说

尽管这可能不起作用-您需要设置一些东西使WPF正常工作,但这不仅仅是使用STA线程的问题:

  • 将SetSynchronizationContext设置为DispatcherSynchronizationContext

    SynchronizationContext.SetSynchronizationContext(新DispatcherSynchronizationContext(Dispatcher.CurrentDispatcher))

  • 创建一个
    System.Windows.Application()

  • 使用Application.LoadComponent()加载并添加任何XAML资源

    var resources=System.Windows.Application.LoadComponent(新Uri(“/Styles.xaml”,UriKind.Relative)); Resources.MergedDictionaries.Add(资源)

  • 您需要以编程方式泵送
    调度程序

    Dispatcher.CurrentDispatcher.PushFrame()


  • 我也有同样的问题。您需要使用TaskScheduler。重要的是设置ApartmentState

    public static async Task Main()
    {
      var taskScheduler = new SingleThreadTaskScheduler(ApartmentState.STA);
      var taskList = new List<Task>();
    
      var updateTask = Task.Run(InstallHelper.CheckForUpdatesAsync);
      updateTask.Wait();
      taskList.Add(updateTask);
      var tasks = await Task.Factory.ContinueWhenAll(taskList.ToArray(), result => 
                        Task.Factory.StartNew( ()=>MyAppSynchronMethodToRunIn_STAThread, 
                        taskScheduler));
    }
    
    公共静态异步任务Main() { var taskScheduler=newsinglethreadtaskscheduler(ApartmentState.STA); var taskList=新列表(); var updateTask=Task.Run(InstallHelper.CheckForUpdatesAsync); updateTask.Wait(); taskList.Add(updateTask); var tasks=wait Task.Factory.ContinueWhenAll(taskList.ToArray(),result=> Task.Factory.StartNew(()=>MyAppSynchronousMethodToRunin\u statThread, 任务调度器); }
    您能做些什么吗?对不起,我完全忘了把它放进去:PresentationCore.dll中发生了“System.InvalidOperationException”类型的异常,但没有在用户代码中处理。其他信息:调用线程必须是STA,因为许多UI组件都需要这样做。为什么调用应用程序试图在非UI线程上创建UI对象?请告诉我Dispatcher解决方案是如何工作的?因为异常,即::“PresentationCore.dll中发生了类型为'System.InvalidOperationException'的异常,但未在用户代码中处理。其他信息:调用线程必须是STA,因为许多UI组件都需要它。”在代码到达我的类的构造函数时立即引发。因此,我必须在这一点之前做一些事情,“Dispatcher解决方案”仍然要求您从STA线程调用—正如异常所说—因此,一旦您这样做了(您可以通过从应用程序调用库方法来完成),您可能仍然需要完成我上面为“Dispatcher解决方案”概述的步骤。我再次建议您不要走这条路——而是创建另一个WPF应用程序。