2016-06-29 18 views
0

C#コードからC#のUIコードにコールバックイベントメッセージを送信する必要があるWindows 8電話アプリケーションを開発しています。以下は、私がコールバック関数を作成してC++コードへのポインタを送るC#コードです。 C++コードは、この関数ポインタを使用して非同期イベントメッセージをUIに送信できます。C++コードからC#コードにコールバックを送信するときのアクセス違反の読み取り位置0x00000004

C#コード

以下
public partial class MainPage 
{ 
     public MainPage() 
     { 
      InitializeComponent(); 
     } 
     public delegate void CallBack([In][MarshalAs(UnmanagedType.LPStr)] string strParam); 
     [DllImport("Test.dll", CallingConvention = CallingConvention.StdCall)] 
     public static extern void PerformActionWithCallBack(int x); 

     void DemonstrateCallBack() 
     { 
      int x; 
      CallBack callback_delegate = new CallBack(CallBackFunction); 
      // Converting callback_delegate into a function pointer that can be 
      // used in unmanaged code. 
      IntPtr intptr_delegate = Marshal.GetFunctionPointerForDelegate(callback_delegate); 

      //Getting the pointer into integer value and sending it to C++ 

      x = (int)intptr_delegate; 

      testApp.PerformActionWithCallBack(x); 
     } 

     //CallBack function in which event messages will be received 
     void CallBackFunction([In][MarshalAs(UnmanagedType.LPStr)] string strParam) 
     { 
      if (Dispatcher.CheckAccess() == false) 
      { 
       //Updating the text block with the received message 
       Dispatcher.BeginInvoke(() => MyTextBlock.Text = strParam); 
      } 
      else 
      { 
       MyTextBlock.Text = "Update directly"; 
      } 
     } 
} 

私がイベントメッセージを取得することができています。このコードでC#

//Callback function prototype 
typedef void(__stdcall *PCallBack)(LPSTR s); 
LPSTR cbMsg = NULL; 

//Global instance callback function 
PCallBack gUICallback; 

void TestApp::PerformActionWithCallBack(int x) 
{ 
    //Assigning the received calllback function pointer from C# to global function pointer 
    gUICallback = (PCallBack)x; 
} 

//This function will send event messages to C# 
void SendCallbackMsg() 
{ 
    while(1) 
    { 
     cbMsg = "Hello"; 
     Sleep(100); 
     gUICallback(cbMsg); 
     cbMsg = "Hi"; 
     Sleep(100); 
     gUICallback(cbMsg); 
    } 
} 

にイベントメッセージを送信しますC++のコードがありますC#succcessfully、しかし、650-700 calllbacksを送った後、私のアプリケーションはアクセス違反の例外を出し、その後は何も動かない。私は関数ポインタをC#からC++に渡しているが、それを解決することはできないと思っている。

答えて

2

問題は、callback_delegateがガベージコレクトされることです。

MSDNは手動でマネージコードからのガベージコレクタによって収集されてからデリゲートを保持しなければならない

言います。ガベージコレクタは、アンマネージコードへの参照を追跡しません。

私はこのように私はCallbackFunctionの静的をしなければならないとき、この

public partial class MainPage 
{ 
    private CallBack _callBackDelegate = null; 
    public MainPage() 
    { 
     InitializeComponent(); 
    } 
    public delegate void CallBack([In][MarshalAs(UnmanagedType.LPStr)] string strParam); 
    [DllImport("Test.dll", CallingConvention = CallingConvention.StdCall)] 
    public static extern void PerformActionWithCallBack(int x); 

    void DemonstrateCallBack() 
    { 
     _callBackDelegate = new CallBack(CallBackFunction); 
     int x; 

     // Converting _callBackDelegate into a function pointer that can be 
     // used in unmanaged code. 
     IntPtr intptr_delegate = Marshal.GetFunctionPointerForDelegate(_callBackDelegate); 

     //Getting the pointer into integer value and sending it to C++ 

     x = (int)intptr_delegate; 

     testApp.PerformActionWithCallBack(x); 
    } 

    //CallBack function in which event messages will be received 
    void CallBackFunction([In][MarshalAs(UnmanagedType.LPStr)] string strParam) 
    { 
     if (Dispatcher.CheckAccess() == false) 
     { 
      //Updating the text block with the received message 
      Dispatcher.BeginInvoke(() => MyTextBlock.Text = strParam); 
     } 
     else 
     { 
      MyTextBlock.Text = "Update directly"; 
     } 
    } 
} 
+0

を試してみてください。それ以外の場合、CallBackDelegateの初期化は "new CallBack(CallBackFunction);" "フィールド初期化子が非静的フィールド/メソッドを参照できません"というエラーが返されます。 CallbackFunctionを静的にしてCallbackFunction内のDispatcherオブジェクトにアクセスできない場合は、「静的でないフィールド/メトトにオブジェクト参照が必要です」というエラーが表示されます。デッドロックのように見えます。ありがとうございました。 –

+0

@SanjeevKumar申し訳ありませんが、私はC#プログラマーではないので間違いました。この変数をコンストラクタまたは 'void DemonstrateCallback()'メソッドで初期化してクラスに残し、静的でないようにするだけです。私は私の答えを編集して固定した –

+0

帽子オフV.クラフチェンコ、あなたは私の問題を解決しました。それはうまくいっている。あなたに大きなおかげです。 –

関連する問題