2016-03-20 12 views
-1

私はVB.NetのファイルブラウザでMonoフレームワークのUbuntu上で動作しています。私は検索機能を実装することに決めたまで、すべてうまくいっていた。私は検索が新しいタスクで実行されるように設定して、ユーザーはフォームから取り消すことができます。これは、Windows上で正常に動作しますが、モノラルで実行した場合、私は奇妙な結果を得る:時々フォームのフリーズが(まだ周りにドラッグすることができますが、内部のすべてが応答しない)タスクのファイルを再帰的に検索するとMonoでフォームがフリーズする

  • 時々、いくつかの検索結果が出てきますフォームがフリーズする
  • フォームがフリーズしているので、キャンセルボタンをクリックすることができず、強制終了する必要があります。
  • エラーメッセージや例外はありません。
  • 時にはフォームアーティファクト理論的には、検索コードが別のタスクに

を実行しているにもかかわらず、画面上でドラッグ場合、私は、全体を通して「Application.DoEventsを()」を挿入しようとしたが、それは助けにはなりませんでした。私はタスクなしでUIスレッド上でコードを実行しようとしましたが、明らかにすべてがフリーズするだけです。ここで

はコードです:

検索()メソッドは、表示され、キャンセルボタンを呼ばれたときに、テキストボックスを介して呼び出され、クリックされた場合は、()

Dim tokenSource2 As New CancellationTokenSource() 
Dim ct As CancellationToken = tokenSource2.Token 

Private Sub Search(ByVal txt As String, ByVal dir As String) 
    CancelSearch() 
    tokenSource2 = New CancellationTokenSource() 
    ct = tokenSource2.Token 
    pnl_cancelsearch.Show() 
    Dim t As Task = Task.Factory.StartNew(Sub() 
               If ct.IsCancellationRequested Then 
                Exit Sub 
               End If 
               ListView1.Clear() 
               Dim iscasesensitive As Boolean = ConfigManager.SearchIsCaseSensitive 
               If Not searchhistory.Contains(txt) Then 
                searchhistory.Add(txt) 
                combo_search.Items.Add(txt) 
               End If 
               If ct.IsCancellationRequested Then 
                Exit Sub 
               End If 
               If dir = "" Then 
                For Each item As String In Directory.GetLogicalDrives 
                 If ct.IsCancellationRequested Then 
                  Exit Sub 
                 End If 
                 SearchRec(txt, item, iscasesensitive) 
                Next 
               Else 
                SearchRec(txt, dir) 
               End If 
               pnl_cancelsearch.Hide() 
              End Sub) 
End Sub 

Private Sub SearchRec(ByVal txt As String, ByVal rootdir As String, Optional ByVal casesensitive As Boolean = True) 
    For Each item As String In Directory.GetFiles(rootdir) 
     If ct.IsCancellationRequested Then 
      Exit Sub 
     End If 
     If casesensitive Then 
      If item.Contains(txt) Then 
       AddItem(item) 
      End If 
     Else 
      If item.ToLower.Contains(txt.ToLower) Then 
       AddItem(item) 
      End If 
     End If 
    Next 
    For Each item As String In Directory.GetDirectories(rootdir) 
     If ct.IsCancellationRequested Then 
      Exit Sub 
     End If 
     SearchRec(txt, item) 
    Next 
End Sub 
tokenSource2.Cancelを呼び出します

どうすれば修正できますか?私は間違って何をしていますか?それは、Windowsでは完全に正常に動作しますが、Monoでは動作しません。

答えて

0

他のユーザーのおかげで、このソリューションは完全に機能するUIを更新するときにはBeginInvokeを使用することでした。

+1

あとで「EndInvoke」を呼び出すことを忘れないでください。 –

0

UIが変更されていて、タスクが新しいスレッドとして実行されるようにしています(待機スレッドを使用していないため、スレッドがメインスレッドで実行されている場合は共有時間がありません) 。

新しいスレッドを作成するようにタスクを強制すると、使用するタスクスケジューラとして明示的にTaskScheduler.Defaultを設定する必要がある場合は、UIコードによってクロススレッド例外が発生します。新しいスレッドでタスクを強制的に実行しない場合、それをブロックしているメインスレッドで実行されます。

Monoフォームの実装が最低であるため、Windowsよりもはるかに低速ですが、Windowsでは完全に速く、Monoを使用する別のOSでは速度が遅く、 UIの更新を確認します。

まず、Forms on Monoの使用を避け、GTK#または別のUIキットを使用してください。

また、データロジックからUIロジックを分離し、(タスクまたはスレッドプールを使用して)すべてのデータを取得するタスクを作成し、UIを更新したら、それを見つけることができますUIの更新が遅いためです。

+0

UIが完全にフリーズして応答性に戻ることはありません。強制終了する必要があります。私はクロススレッドの問題を理解していますが、アイテムが見つかるとリストビューにデータを入れるようにしてください。さもなければ、ユーザは空リストビューでしばらく待つことができます。 – TheRyan722

+0

次に、UIコードを起動または開始する必要があります – Gusman

+0

BeginInvokeは私が探していたものでした – TheRyan722

関連する問題