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 来实现您的对象,请查看我的回答以获取更多信息。