使用线程 C# 中的 VC++ 6.0 COM DLL

Using VC++ 6.0 COM DLL from Threads C#

本文关键字:COM DLL VC++ 中的 线程      更新时间:2023-10-16

BackGround:

我们使用VC++6.0创建了DLL。接口中的此DLL具有将消息发送到我们的服务器的函数。因此,外部应用程序通过传递输入参数来调用我们的 DLL 函数,我们的 DLL 使用 TCP/IP 将此消息发送到服务器,并为调用方返回输出。

DLL 使用以下设置进行编译

DLL的主看起来像这样

我在 C#(框架 2.0(中创建了一个 samll 应用程序,该应用程序创建线程来调用 DLL 的函数。发生的情况是第二个线程被阻塞,直到第一个线程尚未完成作业。

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using PAGAMENTOLib;
using log4net;
using log4net.Config;
using System.Configuration;

namespace ThreadTestAPI
{
class Program
{
public static ILog log = LogManager.GetLogger(typeof(Program));
argpayClass apiFunctions = new argpayClass();
static void Main(string[] args)
{

XmlConfigurator.Configure();
List<string> Ip_List = new List<string>();
List<string> Ip_port = new List<string>();
int MAX_THREAD = Convert.ToInt32(ConfigurationManager.AppSettings["MAX_THREAD"].ToString());
string ReplacePattern = string.Empty;
string IP = ConfigurationManager.AppSettings["IP"].ToString();
string PORT = ConfigurationManager.AppSettings["PORT"].ToString();
Program call = new Program();
//int LastPart = Convert.ToInt32(IP.Split('*')[1]);
//string PatterntoReplase = "*" + LastPart;
log.Info("-------------------------------------------------------------------------");
log.Info("                      Started Program                                     ");
log.Info("-------------------------------------------------------------------------");
List<Thread> ThreadList = new List<Thread>(); //Added by Asif Iqbal
WaitAllThreads waitThreads = new WaitAllThreads();
List<Thread> myPOSthread = new List<Thread>();
ParamIn param = new ParamIn();
for (int i = 0; i < MAX_THREAD; i++)
{
Thread thread = new Thread(new ParameterizedThreadStart(call.CallApiFunction));
thread.Name = "Thread " + i;

param.Ped_ip = IP;
log.Info("Thread Name is : " + thread.Name);
log.Info("IP is " + param.Ped_ip);
param.PedPort = PORT.Replace("*",i.ToString());
log.Info("Port is " + param.PedPort);
param.Amount = i;
param.port_listener = "0";
param.DatiAgg = "Thread " + i; 
ThreadList.Add(thread);
thread.IsBackground = true;
thread.TrySetApartmentState(ApartmentState.MTA);

thread.Start(param);
myPOSthread.Add(thread);
Console.WriteLine("***********************************************************");
Console.WriteLine("Thread Name: " + thread.Name);
System.Threading.Thread.Sleep(250);

}

}
[MTAThread]
public void CallApiFunction(object param)
{

log.Info("Calling Api function");
ParamIn members = (ParamIn)param;
//argpayClass apiFunctions = new argpayClass();

string Response = string.Empty;
apiFunctions.PagamentoTCP(0,500,ref members.Ped_ip,Convert.ToInt32(members.PedPort),ref members.DatiAgg,ref Response);
log.Info("IP is " + members.PedPort + ".Response Received from Api is: " + Response);

}
}
public class ParamIn
{
public int Amount;
public string DatiAgg;
public string PedPort;
public string Ped_ip;
public string ip_listener;
public string port_listener;
public int tmo;
public int PrintTicket;
public int Advance;
public ParamIn()
{
Amount = 0;
DatiAgg = "";
Ped_ip = "";
PedPort ="";
port_listener = "";
ip_listener = "";
tmo = 0;
PrintTicket = 0;
}

}

}

我尝试使用

CoInitializeEx(NULL, COINIT_MULTITHREADED); 

在 DLL 主,但没有成功。我也改变了这个,但仍然相同的行为

public CComObjectRootEx<CComSingleThreadModel> 
to  public CComObjectRootEx<CComMultiThreadModel>

有谁知道为什么直到第一个线程正在进行时才调用 dll 函数?

而在 C# 中,线程创建正确。每个线程都完成作业,但不会完成其他线程的工作。它必须等待。

如果你知道对象的实现是线程安全的,并且想要告诉 .NET,请在 COM 对象中实现IMarshal接口。

使用 CoCreateFreeThreadedMarshaler 创建封送拆收器,当 .NET 通过QueryInterface调用请求IMarshal接口时返回封送拆收器。

如果您正在使用 ATL 来实现您的对象,请查看我的回答以获取更多信息。