C#线程异常
我有一个外部组件(C++),我想从我的C#代码中调用它 代码如下所示:C#线程异常,c#,.net,com,sta,C#,.net,Com,Sta,我有一个外部组件(C++),我想从我的C#代码中调用它 代码如下所示: using System.Text; using System.Threading; using System.Threading.Tasks; namespace dgTEST { class Program { [STAThread] static void Main(string[] args) { ExtComponentCal
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();
}
}
}
static void Main(string[] args)
{
Thread t = new Thread(new ThreadStart(() =>
{
ExtComponentCaller extCompCaller = new ExtComponentCaller();
result = extCompCaller.Call(input);
}));
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
}
所以问题是,在第一次调用时,它运行良好,外部组件调用,我得到了结果
但当我尝试在另一个线程中调用它时,我遇到了一个异常:
System.InvalidCastException:无法强制转换类型为“System.\u ComObject”的COM对象。
我敢肯定,这个例外被抛出了,因为这个线程。因为如果我从主函数中删除[StatThread]属性,那么外部组件的第一次调用也会发生同样的情况,这很好
如何从其他线程调用此外部组件以消除此异常
更新-------------
现在发生了另一件疯狂的事情。当我使用F5从Visual Studio启动程序时,问题也会出现在第一次调用中,但是当我直接执行binary.exe文件时,它正在工作(从另一个线程它不是:())。
如果我将构建从Debug切换到Release,并使用F5从visualstudio启动它,那么第一个调用将再次工作
为什么会这样
提前谢谢你的帮助
致以最良好的祝愿,
Zoli线程从来都不是一个小细节。如果代码没有明确记录以支持线程,那么99%的可能性是它不支持线程 显然,这个组件不支持线程。创建另一个STA线程并不是一个神奇的解决方案,它仍然是一个不同的线程。InvalidCastException告诉您,它还缺少代理/存根支持,这是封送来自工作线程的调用所必需的,就像您正在尝试创建的线程一样。这是执行任务所必需的对非线程安全代码的ad-safe调用。尽管您确实违反了[StatThread]的约定,但它必须泵送消息循环。正是消息循环允许从工作线程调用非线程安全的组件。您从Application.Run()获得消息循环 这就是责任所在。它不是线程安全的。即使修复主线程或要求供应商或作者向您提供代理/存根,您仍然没有完成您计划要做的事情,它实际上不会在您创建的工作线程上运行。因此,它必须如下所示:
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();
}
}
}
static void Main(string[] args)
{
Thread t = new Thread(new ThreadStart(() =>
{
ExtComponentCaller extCompCaller = new ExtComponentCaller();
result = extCompCaller.Call(input);
}));
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
}
这将在您进行调用的同一线程上创建对象,因此它是线程安全的。仍然存在此工作线程不泵送消息循环的问题,COM组件往往依赖于此。您将从死锁或未运行的事件中找出这是否是问题。如果它在测试程序中已经正常工作,则am当您从主线程调用它时,您可能可以不使用泵送。当您在标记为STA的线程中执行整个工作(创建COM实例和运行方法)时会发生什么情况?可能此COM对象在注册表中标记为STA,并且在不同的COM单元中无法正常工作(从MTA到STA或从STA到MTA)可能是由于编码方式的错误。我得到了相同的异常:(.但是主功能是STA,线程是在那里创建的。线程也设置为STA,所以我不明白。这可能是由于组件中的错误。当所有事情都在一个STA线程中完成时,它应该可以工作。你是说主线程是一个“单线程单元”您正在该线程上创建一个COM对象,然后启动另一个线程(现在是多线程的)并尝试访问该COM对象(同样是在单线程单元中创建的)来自多个线程。实际上不受支持。是的,我尝试在其他线程中创建所有内容,但在这种情况下,主函数不应该是[StatThread],否则我会遇到相同的异常。感谢您的评论!非常好的描述,感谢您的帮助!:)现在它正在我的测试程序中工作。我将把它放到真实的环境中,希望一切都会好起来:)。