1

我的 C++ 类中有几个成员函数,我将它们打包为 dll 并尝试在 C# 应用程序中使用它们。我试图通过简单地使用线程执行它们然后将它们分离()来创建两个异步函数,这样它们就不会阻塞调用者线程直到它们结束。
在基于 C++ 的应用程序中,每当我使用线程以这种方式调用函数时,它们都可以工作,但是当我尝试从 C# 调用我的一个异步函数时,它们似乎执行但没有结果。
这两个异步函数应该在完成工作后创建文本文件,但是它们的普通对应部分却没有!
我将发布我的类定义的片段以及我的 C 包装器(用于 dll )和我的 c# 应用程序部分。

//xGramManipulator.h file
#pragma once
#include <regex>
#include <string>
#include <map>
#include <thread>
#include <mutex>
#include <vector>

class xGramManipulator
{

public:
    xGramManipulator();
    xGramManipulator(wchar_t* fileToRead);
    xGramManipulator(std::wregex monoReg, std::wregex biReg, wchar_t* fileToRead = L"ftext.txt");
    ~xGramManipulator();

    double CreateMonoGram();
    double ReadMonoGram();
    void SaveMonoGram();

    double CreateBiGram();
    double ReadBiGram();
    void SaveBiGram();

    double CreateLists();
    void CreateMonoGramAsync();
    void CreateBiGramAsync();



priavte: 
    template<class TypeOne, class TypeTwo>
    void WriteToFile(const wchar_t* filePath, std::map<TypeOne, TypeTwo>& container);

private:
    std::map<std::wstring, int> monogramStatMap;
    std::map<std::wstring, int> bigramStatMap;
    std::map<std::wstring, std::wstring> bigramListMap;
    std::vector<std::wstring> nextWordResults;
std::unordered_multimap< std::wstring, std::wstring > container;

    std::mutex mutex_;

    wchar_t* fileToReadFrom;
    wchar_t **CStringArraybuffer;

    std::wregex monoRegx;
    std::wregex biRegx;

    std::thread tr1;
    std::thread tr2;

    std::chrono::high_resolution_clock::time_point startTime;
std::chrono::high_resolution_clock::time_point endTime;
std::chrono::high_resolution_clock::time_point elapsedTime;

};

template <class TypeOne, class TypeTwo>
void xGramManipulator::WriteToFile(const wchar_t* filePath, std::map<TypeOne, TypeTwo>& container)
{
    //Because of possible use of threads and inorder to avoid any thread interferance 
    //i decided to declare it local instead of global.
    FILE* filePointer;

    //for converting To UTF8 so that our contents are in farsi and not some numeric nonsense!
    _wfopen_s(&filePointer, filePath, L"w");
    _setmode(_fileno(filePointer), _O_U8TEXT);

    wofstream output(filePointer);

    for (auto item : container)
    {
        //write output to file
        output << item.first << " : " << item.second << endl;
    }

    fclose(filePointer);
}

//xGramManipulator.cpp 文件

#include <regex>
#include <fstream>
#include <iostream>
#include <string>
#include <map>
#include <fcntl.h>  //for _wfopen_s
#include <io.h> //for _setmode
#include <memory>   //for shared_ptr
#include <chrono>   //for time benchmarks
#include <thread>
#include <mutex>
#include <unordered_map>
#include <algorithm>
#include <vector>
#include "xGramManipulator.h"

using namespace std;
using namespace chrono;
typedef high_resolution_clock Time;

xGramManipulator::xGramManipulator() : monoRegx(L"\\w+"), biRegx(L"\\w+ \\w+"), fileToReadFrom(L"ftext.txt")
{}
xGramManipulator::xGramManipulator(wchar_t* fileToRead) : monoRegx(L"\\w+"), biRegx(L"\\w+ \\w+"), fileToReadFrom(fileToRead)
{
    if (!FileExits(fileToReadFrom))
    {
        cout << "File doesnt Exists" << endl;
    }
}
xGramManipulator::xGramManipulator(wregex monoReg, wregex biReg, wchar_t* fileToRead) : monoRegx(monoReg), biRegx(biReg), fileToReadFrom(fileToRead)
{
    if (!FileExits(fileToReadFrom))
    {
        cout << "File doesnt Exists";
    }
}

xGramManipulator::~xGramManipulator()
{
}

//Reads from a file specified in the constructor or through SetFilePathToReadFrom() function
//And then creates a list of monograms.When function execution ends, the elapsed time is returned.
double xGramManipulator::CreateMonoGram()
{
    Time::time_point start = Time::now();
    ReadMonoGram();
    SaveMonoGram();
    Time::time_point end = Time::now();

    return ElapsedTime(start, end);
}

//Reads from a file specified in the constructor or through SetFilePathToReadFrom() function
//And then creates a list of bigrams.When function execution ends, the elapsed time is returned.
double xGramManipulator::CreateBiGram()
{
    Time::time_point  start = Time::now();
    ReadBiGram();
    SaveBiGram();
    Time::time_point  end = Time::now();

    return ElapsedTime(start, end);
}

double xGramManipulator::ReadMonoGram()
{
    FILE* filePointer;
    wstring inputString = L"";
    Time::time_point start = Time::now();
    try
    {

        //converting UTF16 to UTF8 so that we dont get rubbish result!
        _wfopen_s(&filePointer, fileToReadFrom, L"r");
        _setmode(_fileno(filePointer), _O_U8TEXT);

        wifstream file(filePointer);

        monogramStatMap.clear();
        while (file.good())
        {
            getline(file, inputString);

            for (wsregex_iterator it(inputString.begin(), inputString.end(), monoRegx), it_end; it != it_end; ++it)
            {
                //Filling the bigram container
                //unorderedmap estrefade beshe baraye soorate bishtar
                monogramStatMap[(wstring) (*it)[0]]++;
            }
        }
        fclose(filePointer);

    }
    catch (exception ex)
    {
        cout << ex.what() << endl;
    }

    Time::time_point end = Time::now();
    return ElapsedTime(start, end);
}

void xGramManipulator::SaveMonoGram()
{
    WriteToFile(L"monogramLists.txt", monogramStatMap);
}

double xGramManipulator::ReadBiGram()
{
    FILE* filePointer;
    wstring inputString = L"";
    wstring wstr = L"";
    Time::time_point start = Time::now();
    try
    {

        //converting UTF16 to UTF8 so that we dont get rubbish result!
        _wfopen_s(&filePointer, fileToReadFrom, L"r");
        _setmode(_fileno(filePointer), _O_U8TEXT);

        wifstream file(filePointer);

        bigramStatMap.clear();
        container.clear();

        while (file.good())
        {
            getline(file, inputString);

            for (wsregex_iterator it(inputString.begin(), inputString.end(), biRegx), it_end; it != it_end; ++it)
            {
                //Filling the bigram container
                wstr = (wstring) (*it)[0];
                bigramStatMap[wstr]++;

                //spliting the two words into two items.
                bigramListMap[wstr.substr(0, wstr.find(L' '))] = wstr.substr(wstr.find(L' '), wstr.size());
                container.emplace(wstr.substr(0, wstr.find(L' ')), wstr.substr(wstr.find(L' '), wstr.size()));
            }
        }
        fclose(filePointer);

    }
    catch (exception ex)
    {
        cout << ex.what() << endl;
    }

    Time::time_point end = Time::now();
    return ElapsedTime(start, end);
}

void xGramManipulator::SaveBiGram()
{
    WriteToFile(L"bigramStatList.txt", bigramStatMap);
    WriteToFile(L"bigramList.txt", bigramListMap);
}

double xGramManipulator::CreateLists()
{
    startTime = Time::now();
    tr1 = thread(&xGramManipulator::CreateMonoGram, this);
    tr2 = thread(&xGramManipulator::CreateBiGram, this);
    tr1.join();
    tr2.join();
    endTime = Time::now();

    return ElapsedTime(startTime, endTime);
}

void xGramManipulator::CreateMonoGramAsync()
{
    thread t(&xGramManipulator::ReadMonoGram, this);
    t.detach();
}

void xGramManipulator::CreateBiGramAsync()
{
    //static_cast<void (xGramManipulator::*)()>(&xGramManipulator::ReadMonoGram)
    thread t = thread(&xGramManipulator::ReadBiGram, this);
    t.detach();
}

这是我的 Dll 定义://CDll.h

#ifdef CDLL_EXPORTS
#define CDLL_API __declspec(dllexport)
#else
#define CDLL_API __declspec(dllimport)
#endif

extern "C"
{
    CDLL_API double CreateMonoAndBioGramLists(void);                            //reads and creates two files for each
    CDLL_API double CreateMonoGram(void);                                       //reads and creates a file 
    CDLL_API double CreateBiGram(void);                                         //reads and creates a file
    CDLL_API wchar_t** GetResults(wchar_t* word , int threshold, int* lemgth);              //returns the result of the search

    CDLL_API double ReadMonoGram(void);
    CDLL_API double ReadBiGram(void);

    CDLL_API void CreateMonoGramAsync(void);
    CDLL_API void CreateBiGramAsync(void);

    CDLL_API void*  CreateHandle();
    CDLL_API void*  GetCurrentHandle();
    CDLL_API void  DisposeCurrentHandle();
    CDLL_API void  SetCurrentHandle(void* handle);
    CDLL_API void*  GetHandle();
    CDLL_API void  DisposeHandle(void*);
}

//CDLL.cpp

#include "CDll.h"
#include "xGramManipulator.h"

#define DLL_EXPORT

extern "C"
{
    xGramManipulator *xG;
    CDLL_API double CreateMonoAndBioGramLists(void)
    {
        //return xG.CreateLists();
        xG = reinterpret_cast<xGramManipulator*>(GetHandle());
        return xG->CreateLists();
    }
    CDLL_API double CreateMonoGram(void)
    {
        //return xG.CreateMonoGram();
        xG = reinterpret_cast<xGramManipulator*>(GetHandle());
        return xG->CreateMonoGram();
    }
    CDLL_API double CreateBiGram(void)
    {
        //return xG.CreateBiGram();
        xG = reinterpret_cast<xGramManipulator*>(GetHandle());
        return xG->CreateBiGram();
    }
    CDLL_API wchar_t** GetResults(wchar_t* word, int threshold, int* length)
    {
        //return xG.CGetNextWordsList(word, length, threshold);
        xG = reinterpret_cast<xGramManipulator*>(GetHandle());
        return xG->CGetNextWordsList(word, length, threshold);
    }

    CDLL_API double ReadMonoGram(void)
    {
        //return xG.ReadMonoGram();
        xG = reinterpret_cast<xGramManipulator*>(GetHandle());
        return xG->ReadMonoGram();
    }
    CDLL_API double ReadBiGram(void)
    {
        //return xG.ReadBiGram();
        xG = reinterpret_cast<xGramManipulator*>(GetHandle());
        return xG->ReadBiGram();
    }

    CDLL_API void CreateMonoGramAsync(void)
    {
        //xG.CreateMonoGramAsync();
        xG = reinterpret_cast<xGramManipulator*>(GetHandle());
        return xG->CreateMonoGramAsync();
    }
    CDLL_API void CreateBiGramAsync(void)
    {
        //xG.CreateBiGramAsync();
        xG = reinterpret_cast<xGramManipulator*>(GetHandle());
        return xG->CreateBiGramAsync();
    }

    //Handle operations
    CDLL_API void* CreateHandle()
    {
        if (xG == nullptr)
        {
            xG = new xGramManipulator;
        }
        else
        {
            delete xG;
            xG = new xGramManipulator;
        }
        return reinterpret_cast<void*>(xG);
    }

    CDLL_API void* GetCurrentHandle()
    {
        return reinterpret_cast<void*>(xG);
    }

    CDLL_API void  DisposeCurrentHandle()
    {
        delete xG;
        xG = nullptr;
    }

    CDLL_API void  SetCurrentHandle(void* handle)
    {
        if (handle != nullptr)
        {
            xG = reinterpret_cast<xGramManipulator*>(handle);
        }
        else
        {
            xG = new xGramManipulator;
        }

    }
    //factory utility function
    //ask question on how to do it.
    CDLL_API void* GetHandle()
    {
        HANDLE handle = GetCurrentHandle();
        if (handle != nullptr)
        {
            return handle;
        }
        else
        {
            xG = new xGramManipulator;
            handle = reinterpret_cast <void*>(xG);
        }
        return handle;
    }

    CDLL_API void  DisposeHandle(void* handle)
    {
        xGramManipulator * tmp = reinterpret_cast<xGramManipulator*>(handle);
        delete tmp;
    }

注意:
起初不是

 xGramManipulator *xG;

我有

xGramManipulator xG;  

我只是使用该全局对象来调用成员函数。经过一番思考后,我认为这可能不好,我应该以某种方式使其动态化!?所以我将其更改为当前状态。
请指导我以前的解决方案(使用全局对象 xG)是对还是错,如果错了我会面临什么样的问题?
如果当前的方法是错误的,那我该怎么办?

4

0 回答 0