2016-11-16 4 views
1

私は、データをドラッグアンドドロップして、その上に潜在的に非常に長い操作を実行するアプリケーションを持っています。これは問題なく動作しますが、アプリケーションが処理中にエクスプローラウィンドウがフリーズします。ファイルリストのコピーを取ってすぐに話すように「リリースする」方法はありますか?Fix Drag Drop Freezing Explorer

私の現在のコードは次のとおりです。あなたは、イベントが完了するまで実行できるようにする必要がある

private void MainForm_DragDrop(object sender, DragEventArgs e) 
    { 
     ClearTempFiles(); //Clear all files before populating 
     string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); //Get the filepaths for the dragdrop data 
     List<string> toParse = new List<string>(); 
     foreach (string file in files) 
     { 
      FileAttributes attr = File.GetAttributes(file); 
      if (attr.HasFlag(FileAttributes.Directory)) //If a folder has been included, add all files from within 
      { 
       toParse.AddRange(DirSearch(file)); 
      } 
      else 
      { 
       toParse.Add(file); //Add files 
      } 
     } 
     CurrentJobData = new JobData(toParse); //Create new JobData from these files <---- Takes up to a few minutes with hundreds of files. 
     CurrentJobData.ToTree(treeView1); //Push this data to the TreeView 
    } //Handles the dragdrop of data, populating the solution 
+0

長時間実行されるタスクは、バックグラウンドスレッドで実行する必要があります。 'Task'sまたは' ThreadPool'を使います。 – dymanoid

+1

[BackgroundWorker](https://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v = vs.110).aspx)を使用することもできます。 [backgroundworkerを使用する方法?](http://stackoverflow.com/q/6481304/669576)。 –

+0

この処理が完了するまで、プログラム自体を続行したり、応答(進行状況バーを表示しない)したくないです。それはバックグラウンドで実行できるものではありません。私は単に、Windowsエクスプローラをフリーズすることはちょっとしたことだと思って、その周りに道があるかどうか疑問に思っていました。 –

答えて

0

。 DragDrop操作の性質上、両方のアプリケーションで操作が完了したことを確認する必要があります。 DragDropメッセージがメッセージポンプによって処理されるかどうかだけを知ることができます。それが起こらない限り、エクスプローラはユーザーがドラッグアンドドロップしていることしか想定していません。あなたはDoWork EventHandlerが今力仕事を行いますよ

private void Form1_DragDrop(object sender, DragEventArgs e) 
{  
    // gets all data from Explorer 
    string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); //Get the filepaths for the dragdrop data 

    // don't block the UI thread, that prevents the 
    // processing of both Windows messages in Explorer and your app 
    // to complete, effectively blocking both of them 
    backgroundWorker1.RunWorkerAsync(files); 

    // if you want your form to be unavailable 
    // while processing takes place 
    // set Enabled to false on your form 
    this.Enabled = false; 
} 

:だから、すでにコメントで提案、BackgroundWorkerのを使用しています。 DoWorkEventArgsResultプロパティを設定して、完了したイベントにJobDataを送信する方法に注目してください。あなたが戻ってあなたのTreeViewを記入し、更新することができUIスレッド、上だRunWorkerCompletedのEventHandlerで

// this all runs on a background, non-UI threed 
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    ClearTempFiles(); //Clear all files before populating 

    string[] files = (string[])e.Argument; // this is passed in from RunWorkerAsync 

    List<string> toParse = new List<string>(); 
    foreach (string file in files) 
    { 
     FileAttributes attr = File.GetAttributes(file); 
     if (attr.HasFlag(FileAttributes.Directory)) //If a folder has been included, add all files from within 
     { 
      toParse.AddRange(DirSearch(file)); 
     } 
     else 
     { 
      toParse.Add(file); //Add files 
     } 
    } 

    e.Result = new JobData(toParse); //Create new JobData from these files <---- Takes up to a few minutes with hundreds of files. 
} 

。最終的にフォームが再び有効になり、ユーザーがアプリケーションとやり取りできることを確認してください。

// this runs on the UI thread 
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    CurrentJobData = (JobData) e.Result; 

    CurrentJobData.ToTree(treeView1); //Push this data to the TreeView 

    // set Enabled to true on your controls 
    this.Enabled = true; 
} 

あなたは、進捗状況を報告しますが、UIスレッドにしているので、ProgressChangedのイベントハンドラを使用してくださいとそのハンドラを呼び出すためにBackgroundWorkerの上ReportProgressメソッドを呼び出したい場合。

関連する問題