3 votes

C# DllImport se bloque de manière inattendue

J'ai une application C# avec un composant C++. Je communique avec DllImport entre les modules. L'application fonctionne pendant plusieurs jours sans problème et se plante parfois de manière inattendue.

[DllImport("recorder", CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr start_recording();

Est-il possible d'exécuter la partie C++ dans un conteneur protégé afin que l'application entière ne se plante pas ?

Visualisateur d'événements

Erreur d'application

Faulting application name: Recorder.exe, version: 1.0.0.0, time stamp: 0x59eef7cb
Faulting module name: avformat-57.dll, version: 57.71.100.0, time stamp: 0x00000000
Exception code: 0xc0000005
Fault offset: 0x00000000000d7e7f
Faulting process id: 0x186c
Faulting application start time: 0x01d3620b7e41ef96
Faulting application path: C:\Test\Recorder.exe
Faulting module path: C:\Test\avformat-57.dll
Report Id: 3fde49fc-d2ed-11e7-bf5c-002590abb7d4

Exécution .NET

Application: Recorder.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: exception code c0000005, exception address 000007FEEA407E7F

2voto

OriBS Points 561

En général, certaines conditions provoquent toujours la sortie d'un processus et vous n'avez rien à y faire.

Bien que vous puissiez gérer certaines erreurs en attrapant les exceptions, en définissant un gestionnaire de signaux ou en corrigeant simplement le bogue, cela ne résoudra qu'un cas spécifique et ne vous donnera pas une solution générale, et il est possible que vous ne contrôliez pas du tout le module.

La solution courante dans un tel cas est de séparer le module dans un processus proxy différent, qui communiquera avec votre propre application.

0voto

live2 Points 1557

Vous trouverez ici de plus amples informations sur Communications interprocessus

J'ai décidé d'utiliser NamedPipes est très rapide et je peux communiquer dans les deux sens.

Exemple C++

cout << "Connecting to pipe..." << endl;

// Open the named pipe
// Most of these parameters aren't very relevant for pipes.
HANDLE pipe = CreateFile(
    L"\\\\.\\pipe\\MyServerPipe",
    GENERIC_READ, // only need read access
    FILE_SHARE_READ | FILE_SHARE_WRITE,
    NULL,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    //NULL,
    NULL
);

if (pipe == INVALID_HANDLE_VALUE) {
    cout << "Failed to connect to pipe." << endl;
    // look up error code here using GetLastError()
    system("pause");
    return 1;
}

cout << "Reading data from pipe..." << endl;

// The read operation will block until there is data to read
char buffer[128];
DWORD numBytesRead = 0;
BOOL result = ReadFile(
    pipe,
    buffer, // the data from the pipe will be put here
    127 * sizeof(char), // number of bytes allocated
    &numBytesRead, // this will store number of bytes actually read
    NULL // not using overlapped IO
);

if (result) {
    buffer[numBytesRead / sizeof(char)] = '\0'; // null terminate the string
    cout << "Number of bytes read: " << numBytesRead << endl;
    //wcout << "Message: " << buffer << endl;

    //wstring ws(buffer);
    //string str(ws.begin(), ws.end());
    cout << "Test:" << buffer << endl;

}
else {
    wcout << "Failed to read data from the pipe." << endl;
}

// Close our pipe handle
CloseHandle(pipe);

//wcout << "Done." << endl;

system("pause");
return 0;

C# Obtenir tous les tuyaux disponibles

var listOfPipes = System.IO.Directory.GetFiles(@"\\.\pipe\")

Exemple en C#

using (var pipeServer = new NamedPipeServerStream("MyServerPipe", PipeDirection.InOut))
{
    Console.WriteLine("NamedPipeServerStream object created.");

    // Wait for a client to connect
    Console.Write("Waiting for client connection...");
    pipeServer.WaitForConnection();

    Console.WriteLine("Client connected.");
    try
    {
        using (var bw = new BinaryWriter(pipeServer))
        {
            var data = Encoding.ASCII.GetBytes("SendInformation data1 data2 data3");
            //var data = Encoding.ASCII.GetBytes("Start\r\n");
            bw.Write(data);
        }
    }
    // Catch the IOException that is raised if the pipe is broken
    // or disconnected.
    catch (IOException e)
    {
        Console.WriteLine("ERROR: {0}", e.Message);
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X