Использование VC ++ 6.0 COM DLL из потоков C # - PullRequest
0 голосов
/ 27 августа 2018

BackGround:

У нас есть DLL, созданная с использованием VC ++ 6.0 . Эта DLL в интерфейсе имеет функции, которые отправляют сообщения на наш сервер. Поэтому внешние приложения вызывают функцию нашей DLL, передавая входной параметр, и наша DLL отправляет это сообщение на сервер, используя TCP / IP, и возвращает вывод для вызывающей стороны.

DLL компилируется со следующими настройками

Основная библиотека DLL выглядит следующим образом

Я создал приложение samll в C # (framework 2.0), которое создает поток для вызова функции 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 # темы были созданы правильно. Каждая нить заканчивает работу, но не в паре всех остальных. Это должно ждать.

1 Ответ

0 голосов
/ 28 августа 2018

Если вы знаете, что реализация вашего объекта является поточно-ориентированной, и вы хотите сообщить .NET об этом, внедрите интерфейс IMarshal в свой COM-объект.

Используйте CoCreateFreeThreadedMarshaler для создания маршалера, возвращайте маршалер, когда .NET запрашивает интерфейс IMarshal через QueryInterface вызов.

Если вы используете ATL для реализации своего объекта, посмотрите мой ответ для получения дополнительной информации.

...