2012-01-06 37 views
0

グローバルに宣言された2つのスレッドがあります。フォームロード時に2つのスレッドを開始します。終了ボタンをクリックします。私はパイプを作成しているwhileループと他のスレッドで接続を待っている私はバックグラウンドでDataGridを更新しています形。C#スレッドで保護されたメモリにアクセスしようとしたときにエラーが発生しました

私の質問が十分ではありませんが、コードが非常に大きい場合は、何が起こっているか考えてください。

おかげ

フォーム負荷のコードは

private void frmStatus_Load(object sender, EventArgs e) 
{ 
    Control.CheckForIllegalCrossThreadCalls = false; 
    RefreshStatus = new Thread(RefreshStatusForm); 
    RefreshStatus.IsBackground = true; 
    RefreshStatus.Start(); 

    th = new Thread(this.CreatePipe); 
    th.IsBackground = true; 
    th.Start(); 
} 

ボタン上にあるが

private void btnOk_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     System.Object lockThis = new System.Object(); 

     lock (lockThis) 
     { 
      bCheckVal = false; 

      if (!this.bComplete) 
       stopOperation(); 

      Thread.Sleep(1000); 

      ////////These are the lines in which i get the error 
      if (!th.IsAlive) 
      { 
       th.Join(); 
      } 
      else 
      { 
       th.Abort(); 
      } 

      this.bRefresh = false; 
      Thread.Sleep(1000); 
      if (RefreshStatus.IsAlive) 
      RefreshStatus.Abort(); 
      else 
      RefreshStatus.Join(); 

      ///////////////// 
      this.bFlag = true; 
     } 

     this.Close();   
    } 
    catch (System.Exception ex) 
    { 
    } 
} 

にスレッドによって実行されるコードをクリックしてフォームを閉じるためのコードである

 public void CreatePipe() 
    { 
     try 
     { 
      PipeSecurity pipeSa = new PipeSecurity(); 
      pipeSa.SetAccessRule(new PipeAccessRule("Everyone", 
          PipeAccessRights.ReadWrite, AccessControlType.Allow)); 

      NamedPipeServerStream pipeServer = new NamedPipeServerStream(
       this.strguid,     // The unique pipe name. 
       PipeDirection.InOut,   // The pipe is bi-directional 
       NamedPipeServerStream.MaxAllowedServerInstances); 

      string strMessage = string.Empty; 
      char[] bRequest = new char[BUFFER_SIZE];// Client -> Server 
      int cbBytesRead, cbRequestBytes; 
      StreamReader sr = null; 
      byte[] bReply;       // Server -> Client 
      int cbBytesWritten, cbReplyBytes; 
      int icount = 0; 
      List<string> lsRead = new List<string>(); 
      cbBytesRead = 0; 
      CopyFileThread = new Thread(this.CopyFile); 
      CopyFileThread.IsBackground = true; 
      CopyFileThread.Start(); 
      bool bflag = false; 


      while (true) 
      { 
       this.bComplete = false; 
       bWait = true; 

       try 
       { 




        pipeServer.WaitForConnection(); 

        sr = new StreamReader(pipeServer); 

        //string message = sr.ReadToEnd(); 
        bWait = false; 
        cbRequestBytes = BUFFER_SIZE; 






        string pipeData = string.Empty; 

        pipeData = sr.Read(bRequest, 0, 255).ToString().Trim(); 
        strMessage = new string(bRequest); 




        strMessage = strMessage.Replace("\0", string.Empty); 
        if (strMessage.Contains("Aborted")) 
        { 


         if (pipeServer.IsConnected) 
         { 
          pipeServer.Flush(); 
          pipeServer.Disconnect(); 
         } 
         break; 
        } 
        else 
         if (strMessage.Contains("Completed")) 
         { 
          if (progressBar1.InvokeRequired) 
          { 
           strPercent = "100%"; 
          } 


          if (pipeServer.IsConnected) 
          { 
           pipeServer.Flush(); 
           pipeServer.Disconnect(); 
          } 
          this.bComplete = true; 
          break; 
         } 
        // 26 dec 2011 Comment code ////// 
        if (strMessage == "") 
        { 
         progressBar1.Visible = false; 
         progressBar2.Visible = true; 
        } 
        else 
        { 
         progressBar1.Visible = true; 
         progressBar2.Visible = false; 
        } 

        //// 26 dec 2011 Comment code ////// 

        string[] strStatusMessages = strMessage.Trim().Split(','); 



        // 26 dec 2011 Comment code ////// 
        pipeServer.Flush(); 

        pipeServer.Disconnect(); 



       } 
       catch (System.Exception ex) 
       { 
        //MessageBox.Show(ex.ToString()); 

       } 
      } 


      pipeServer.Close(); 


      if (CopyFileThread.IsAlive) 
       CopyFileThread.Abort(); 
      else 
       CopyFileThread.Join(); 


      MessageBox.Show("Exiting from createpipe 2 Thread :{0}", Thread.CurrentThread.ToString()); 
      return; 
     } 
     catch (Exception ex) 
     { 
      return; 
     } 
    } 

//////////////////////////////

ボイドRefreshStatusForm(){

 while (bRefresh) 
     { 
      if (iRefresh == 1) 
      { 
       GetRefresh(); 
       iRefresh = 0; 
      } 
      else if (iRefresh == 2) 
       break; 
      Thread.Sleep(1000); 
     } 

     MessageBox.Show("Exiting from RefreshStatusForm 2 Thread :{0}", Thread.CurrentThread.ToString()); 
    } 
+1

をので*非常に大きな*でないコードを投稿する - 問題を示して短いものの、完全なプログラムに*だけ*あなたのアプリケーションの関連ビットを抽出します。 (途中で "バックグラウンドフォーム"が意味することは明確ではない) –

+0

エラーが発生した行を分離することはできますか? – robob

+0

////////これは、エラーが発生する行です。 if(!th.IsAlive) { th.Join(); } else { th.Abort(); } this.bRefresh = false; Thread.Sleep(1000); if(RefreshStatus.IsAlive) RefreshStatus.Abort(); else RefreshStatus.Join(); これは行で、私は両方のスレッドをグローバルに宣言しています。 – kunal

答えて

1

スレッドを中止または参加させる必要はありません。正常に終了させるだけの方がいいです。 "whileループで接続を待っている"あなたのスレッドでは、whileループ条件がboolとして設定され、プログラムを終了するときにboolをfalseに設定します。他のスレッドと同様の何かをします。

EDIT1 すべてのだから、最初:

while (true) 
      { 
       this.bComplete = false; 
       bWait = true; 

       try 
       { 

代わり

あなたは

私はスレッドをブロックしようとしている
pipeServer.WaitForConnection(); 

を使用

while(Running) { 

のようなものでなければなりませんそれを非同期タスクに変更する

ただし、したくない場合は、タイムアウトを頻繁に追加してください。

が続い

void btnOk_Click 

ですべてを行う必要が

Running = false; 
bRefresh = false; 

に設定され、その後のスレッドは自分自身を終了します。

EDIT2

使用して設定し、それをアップ:

AsyncCallback myCallback = new AsyncCallback(AsyncPipeCallback); 
pipeServer.BeginWaitForConnection(myCallback, null); 

このメソッド追加:接続がAsyncPipeCallbackが呼び出されたときに発生した今

private void AsyncPipeCallback(IAsyncResult Result) 
{ 
    try 
    { 
     pipeServer.EndWaitForConnection(Result); 
      sr = new StreamReader(pipeServer); 

        //string message = sr.ReadToEnd(); 
        bWait = false; 
        cbRequestBytes = BUFFER_SIZE; 






        string pipeData = string.Empty; 

        pipeData = sr.Read(bRequest, 0, 255).ToString().Trim(); 
        strMessage = new string(bRequest); 




        strMessage = strMessage.Replace("\0", string.Empty); 
        if (strMessage.Contains("Aborted")) 
        { 


         if (pipeServer.IsConnected) 
         { 
          pipeServer.Flush(); 
          pipeServer.Disconnect(); 
         } 
         break; 
        } 
        else 
         if (strMessage.Contains("Completed")) 
         { 
          if (progressBar1.InvokeRequired) 
          { 
           strPercent = "100%"; 
          } 


          if (pipeServer.IsConnected) 
          { 
           pipeServer.Flush(); 
           pipeServer.Disconnect(); 
          } 
          this.bComplete = true; 
          break; 
         } 
        // 26 dec 2011 Comment code ////// 
        if (strMessage == "") 
        { 
         progressBar1.Visible = false; 
         progressBar2.Visible = true; 
        } 
        else 
        { 
         progressBar1.Visible = true; 
         progressBar2.Visible = false; 
        } 

        //// 26 dec 2011 Comment code ////// 

        string[] strStatusMessages = strMessage.Trim().Split(','); 



        // 26 dec 2011 Comment code ////// 
        pipeServer.Flush(); 

        pipeServer.Disconnect(); 


    } 
    catch { } 
    if(Running) 
     pipeServer.BeginWaitForConnection(myCallback, null); 
} 

を。その後、それが終了すると、それがBeginWaitForConnectionであれば、まだ実行中かどうかを確認します。 btnOk_Clickで

は、このように変更します。

private void btnOk_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     System.Object lockThis = new System.Object(); 

     lock (lockThis) 
     { 
      bCheckVal = false; 

      if (!this.bComplete) 
       stopOperation(); 

      Thread.Sleep(1000); 

      Running = false; 
      bRefresh = false; 

      this.bFlag = true; 
     } 

     this.Close();   
    } 
    catch (System.Exception ex) 
    { 
    } 
} 
+0

私が言ったことはあなたのスレッドメソッドを投稿するのが混乱していると私はあなたが何を意味するかを表示します。 – Axis

+0

私は上記のスレッドメソッドをloadとokコードの直下に掲載しました。 – kunal

+0

非同期タスクの設定やタイムアウトに関する助けが必要な場合は、教えてください。 – Axis

0

「しよう保護されたメモリを読み書きする "というのは、通常、範囲外のガベージポインタまたはポインタ算術を持つことを意味します。ガベージポインターは、アプリのハングやクラッシュの原因になります。

あなたのスレッドの質問に答えるには、スレッドの代わりに.NET 4.0 Tasksを使用するのが最も簡単な方法です。タスクはキャンセルトークンを使用して構築できます。メインスレッドは、そのキャンセルトークンを使用して、店舗を閉鎖して家に帰るときのタスクスレッドを知らせることができます。

+0

私たちは.NET Framework 3.5でUiを作っています.4.0の機能を使用することは可能ですか? – kunal

+0

私は、スタック上のローカル変数が128kを超える関数で "書き込み保護されたメモリを読み込もう"という例外を思い出しました。アクセスされた最後のスタックアドレスを超えて64kを超えるスタックメモリにアクセスすると、ページフォルトで失敗します。スタックの一番上の1ページだけが、参照時に割り当てられるように設定されています。解決策は、関数の本体が何かに触れる前に、必要なスタックページをすべて強制的に割り当てるために、コンパイラのコードジェネをスタックに割り当てられた変数の各ページに「触れる」ように変更することでした。私はこれが.netかx86かどうか思い出しません。 – dthorpe

+0

申し訳ありませんが、TPLは.NET 4.0でしか利用できません – dthorpe

関連する問題