我正在调用Process.Start,但它会阻止当前线程.
pInfo = new ProcessStartInfo("C:\\Windows\\notepad.exe");
// Start process
mProcess = new Process();
mProcess.StartInfo = pInfo;
if (mProcess.Start() == false) {
Trace.TraceError("Unable to run process {0}.");
}
Run Code Online (Sandbox Code Playgroud)
即使进程关闭,代码也不再响应.
但是Process.Start真的应该阻止吗?这是怎么回事?
(流程正确启动)
using System;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;
namespace Test
{
class Test
{
[STAThread]
public static void Main()
{
Thread ServerThread = new Thread(AccepterThread);
ServerThread.Start();
Console.WriteLine (" --- Press ENTER to stop service ---");
while (Console.Read() < 0) { Application.DoEvents(); }
Console.WriteLine("Done.");
}
public static void AccepterThread(object data)
{
bool …Run Code Online (Sandbox Code Playgroud) 我需要一个线程池来处理项目中的COM对象ASP.NET.
QueueUserWorkItemSTA(WaitCallback)
Run Code Online (Sandbox Code Playgroud) 我在PowerShell中使用GUI,在点击某些组合框时我会抛出错误.
抛出错误后,我可以放下组合框列表并看到它的内容,但是如果我转移到同一个数据网格视图上的另一个combox,我会在看到下拉列表之前得到相同的初始错误.
我在TechNet PowerShell论坛中发布了这个,并获得了在单线程单元(STA)中运行GUI所需的答案.默认情况下,PowerShell在MTA中运行,但您可以-STA在调用时使用该开关覆盖此(在v2.0中)powershell.exe.
但是,我的GUI只是调用默认的PowerShell应用程序(在MTA模式下),所以我的问题是,有没有办法以编程方式从我的GUI /脚本内部设置apartmentstate?
如果没有,我的下一次尝试将是检测公寓状态并尝试从我的gui的初始加载重新启动我的GUI,例如:
powershell.exe -STA myguiprog.ps1
Run Code Online (Sandbox Code Playgroud)
编辑:
所以我的工作方式有效:
if ([threading.thread]::CurrentThread.GetApartmentState() -eq "MTA") {
& $env:SystemRoot\system32\WindowsPowerShell\v1.0\powershell.exe -sta $MyInvocation.ScriptName
}
Run Code Online (Sandbox Code Playgroud) 我知道在这个主题上有一些关于SO的答案,但是我无法让任何解决方案适合我.我试图从一个从datatemplate中发出的ICommand打开一个新窗口.当实例化新窗口时(在"new MessageWindowP"中),以下两者都会出现上述错误:
使用TPL/FromCurrentSynchronizationContext 更新:有效
public class ChatUserCommand : ICommand
{
public void Execute(object sender)
{
if (sender is UserC)
{
var user = (UserC)sender;
var scheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(new Action<object>(CreateMessageWindow), user,CancellationToken.None, TaskCreationOptions.None,scheduler);
}
}
private void CreateMessageWindow(object o)
{
var user = (UserC)o;
var messageP = new MessageWindowP();
messageP.ViewModel.Participants.Add(user);
messageP.View.Show();
}
}
Run Code Online (Sandbox Code Playgroud)
使用ThreadStart: 更新:不推荐,请参阅Jon的回答
public class ChatUserCommand : ICommand
{
public void Execute(object sender)
{
if (sender is UserC)
{
var user = (UserC)sender;
var t = new …Run Code Online (Sandbox Code Playgroud) 我有一个外部组件(C++),我想从我的C#代码中调用它.
代码是这样的:
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace dgTEST
{
class Program
{
[STAThread]
static void Main(string[] args)
{
ExtComponentCaller extCompCaller = new ExtComponentCaller();
result = extCompCaller.Call(input);
Thread t = new Thread(new ThreadStart(() =>
{
try
{
result = extCompCaller.Call(input);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}));
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
}
}
}
Run Code Online (Sandbox Code Playgroud)
所以问题是,在第一次调用它运行良好时,调用了外部组件,我得到了结果.
但是当我尝试在另一个线程中调用它时,我得到一个异常:System.InvalidCastException:无法转换类型为'System .__ ComObject'的COM对象.... 由于STAThread,我确定这个例外被抛出了.因为如果我从Main函数中删除[STAThread]属性,那么第一次调用外部组件时也会发生同样的情况,这很正常.
如何从其他线程调用此外部组件以摆脱此异常?
UPDATE -------------
现在发生了其他疯狂的事情 当我从Visual Studio使用F5启动程序时,问题也出现在第一次调用中,但是当我直接执行二进制.exe文件时,它正在工作(从另一个线程它不是:().如果我切换从Debug到Release的构建,从Visual Studio和F5开始,第一次调用再次工作.
为什么会这样?
感谢您提前帮助!
最诚挚的问候,佐利
我是WPF的新手,并且有关于WPF和Windows Forms集成的几个问题.
我有一个现有的Visual C#Windows窗体应用程序.我想将它与WPF窗口集成,可以通过单击按钮显示.这是不可能的,因为WPF期望调用线程是一个STAThread,默认情况下WinForm假定该线程是一个MTAThread.我尝试使用公寓状态STAThread生成一个新线程来调用WPF UI,但这不起作用.我尝试使用Dispatcher.BeginInvoke方法和后台工作程序,但没有一个解决了这个问题.
1)我们可以调用WPF窗口/控件而不将Main标记为STAThread吗?如果有可能,有人可以指出我正确的方向吗?2)如果实现此目的的唯一方法是使主线程成为STAThread,那么对应用程序的一般性能/响应性是否会产生任何影响.
提前致谢.
我有这个简单的代码:
public void Run()
{
var invokerThread = new Thread(new ThreadStart(RunOnBackground));
invokerThread.Start();
}
private void RunOnBackground()
{
Trace.WriteLine("hi");
...
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,当运行此代码(来自第三方进程)时,线程并没有真正运行.在进程资源管理器和VS调试器中,我看到线程已创建且其状态为"正在运行".
主线程的公寓是STA,我在内部线程上尝试了STA和MTA.
当我Run()在最后添加到方法时invokerThread.Join();,线程确实运行.但话说回来并没有真正帮助.
我错过了什么?
编辑:以下是有关代码托管的更多信息 -
Run() 方法是通过COM interop从一个进程调用的,该进程也是托管可执行程序集(使用COM互操作的原因是因为系统中的所有其他组件都是本机的).
该方法RunOnBackground()在跟踪之后包括一些代码,并且通常其执行持续10-20秒,包括启动另一个进程并等待其终止.此外,我在代码中还有一些其他区域,我将一些调试信息写入Trace.在调试代码时,Run()像往常一样运行并且在invokerThread.Start();invokerThread的状态为"Running"之后(尽管RunOnBackground()方法中的断点不会停止).
当我添加invokerThread.Join()在结束Run()方法调试器去RunOnBackground() 后的Join().
我有一个主要的STA线程,它调用COM对象上的很多方法,以及一个辅助STA线程,它也在同一个对象上做了很多工作.我希望主线程和辅助线程并行工作(即我希望主要和次要的隔行扫描输出).我知道我需要时不时地在主线程中抽取消息 - 在C++中调用Get/Translate/DispatchMessage就可以了.
但是我遇到了在C#中使用相同策略的问题.起初我在主线程中使用CurrentThread.Join()来控制第二个线程.它没用.然后我转向Application.DoEvents() - 每当我想要第二个线程运行时,我在主线程中调用它.结果是第二个线程快速抓取控件并且不会松开 - 主线程无法继续直到第二个线程全部完成.
我阅读的文档说Application.DoEvents()将处理所有等待事件 - 而GetMessage()只检索一条消息.
什么是正确的做法?是否有C#等价的Get/Translate/DispatchMessage?
谢谢
更新:第二个线程运行得太快,向主STA线程发送大量COM调用消息.我刚刚在第二个线程中添加了延迟以减慢速度.现在两个线程基本上并行运行.但我仍然想知道是否存在与G#等效的GetMessage/TranslateMessage/DispatchMessage.
我正在与WPF合作,正在阅读有关STA的资料.两个问题:
1)STA被定义为由不同的文章代表"单线程亲和力"和"单线程公寓".这说前者:https: //msdn.microsoft.com/en-us/library/ms750441(v = vs1010).aspx 这说后者:https: //msdn.microsoft.com/en-us/库/ ms742522(v = vs.110)的.aspx
这是什么,或STA可以参考这些相关概念中的任何一个?
2)将它们的关系描述为正确:单线程单元是Windows的各个组件使用的模型,线程亲和性是该模型的一个特征吗?
谢谢.