0

はじめに : サーバー [ WCF サービス ライブラリ] とクライアント [ Winform ] があり、クライアントは netTcpBinding を使用してサーバーに接続します。

サーバーの仕事は、ファイルマネージャー機能{新しいフォルダー、移動、コピー、削除、プロパティ、属性、および検索}を使用して、コンピューターファイルをクライアントに共有することです。

ここに画像の説明を入力

問題: 検索関数は再帰関数であり、検索キーを含む (フォルダー/ファイル) 名が見つかると、(クライアント CALLBACK を使用して) 即座にクライアント ListView にアイテムを追加します。
ユーザーが再帰関数_Search()を停止できるようにする検索停止ボタンを追加するまで、すべて完璧に機能していました。検索を停止しようとすると、GUIがフリーズし、フリーズモードから戻ることはありません。私は「デバッグを停止」します。
実際、デバッグモードで検索機能の何が問題なのかを確認するためにポイントを設定すると、機能して検索が停止します。

これは私が検索に使用するコードです:

WCF ライブラリ側:

     [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerSession)]
  public class MainService : IFileManager,ITaskManager
  {

    IFileManagerCallback callback = OperationContext.Current.GetCallbackChannel<IFileManagerCallback>();

 bool stopSearch = false;

    public void StopSearch()    //client call this function to stop SEARCHING.
    {
        stopSearch = true;
    }

    public void Search(string path, string name)     //client call this function to start searching
    {
        _Search(path, name);
        callback.SearchEnd();
        if (stopSearch)
        {
            callback.InfoLabel("Search Cancelled", InfoState.Info);
            stopSearch = false;
            return;
        }
        callback.InfoLabel("Search Done.", InfoState.Done);
    }

    private void _Search(string path, string name)    //the evil recursive function
    {
        if (stopSearch) return;
        DirectoryInfo Roots = new DirectoryInfo(path);

        foreach (FileInfo file in Roots.GetFiles())
        {
            if (stopSearch) return;
            if (file.Name.IndexOf(name, StringComparison.InvariantCultureIgnoreCase) > -1)
            {
                _File item = new _File();
                item.Name = file.Name;
                item.Size = file.Length;
                item.Path = file.FullName;
                callback.File(item);
            }
        }
        foreach (DirectoryInfo folder in Roots.GetDirectories())
        {
            if (stopSearch) return;
            if (folder.Name.IndexOf(name, StringComparison.InvariantCultureIgnoreCase) > -1)
            {
                _Folder item = new _Folder();
                item.Name = folder.Name;
                item.Path = folder.FullName;
                callback.Folder(item);
            }
            _Search(folder.FullName, name);
        }
    } 
 }

WCF インターフェイス:

  [ServiceContract(CallbackContract = typeof(IFileManagerCallback))]
public interface IFileManager
{
    [OperationContract]
    void StopSearch();
     [OperationContract(IsOneWay = true)]
    void Search(string path, string name);
}

     public interface IFileManagerCallback
{
    [OperationContract]
    void File(_File file);

    [OperationContract]
    void Folder(_Folder folder);

    [OperationContract]
    void InfoLabel(string value, InfoState state);

    [OperationContract]
    void SearchEnd();

}

クライアント側 :

 class Callback : IFileManagerCallback
{
    public delegate void OnFileReceived(object sender, _File item);
    private OnFileReceived _fileReceivedHandler = null;
    public event OnFileReceived OnFileReceivedEvent
    {
        add { _fileReceivedHandler += value; }
        remove { _fileReceivedHandler -= value; }
    }
    private void RaiseFileEvents(_File file)
    {
        if (_fileReceivedHandler != null)
        {
            _fileReceivedHandler(this, file);
        }
    }
    public void File(_File file)
    {
        RaiseFileEvents(file);
    }
    // **I WILL AVOID POSTING Folder event and handler it's the same of the file.**
    public void Folder(_Folder folder)
    {
        RaiseFolderEvents(folder);
    }

クライアント Form1.cs :

  public partial class Form1 : Form
{

       private void callback_FileReceivedEvent(object sender, _File file)
    {
        ListViewItem item = new ListViewItem();
        item.Text = file.Name;
        item.ToolTipText = file.Path;
        item.Tag = item.ImageIndex;
        item.Name = item.Text;
        item.SubItems.Add(CnvrtUnit(file.Size));
        item.Group = listView1.Groups[0];
        item.ImageIndex = _iconListManager.AddFileIcon(file.Path);
        listView1.Items.Add(item);
    }
    bool IsSearch = false;
    private void btnSearch_Click(object sender, EventArgs e)
    {
        if (!IsSearch)
        {
           IsSearch = true;
           listView1.Items.Clear();
           client.Search(currAddress, txtAddress.Text);
           return;
        }
        client.StopSearch();
    }
    public void StopSearching()
    {
        UpdateLabel();    //updating GUI label "Selected 0:,Items: 0"
        IsSearch = false;
    }
}

私はそれを修正することについて本当に混乱しています.質問に正しいタイトルを選択したかどうかわからないので、非同期コールバックが必要なためにそれが起こっている場合、検索関数と非同期コールバックをWCFで変換するにはどうすればよいですか?

4

2 に答える 2

0

私は解決策を見つけましたが、完璧ではないかもしれませんが、Thread.Abort を使用して停止する必要がありました。

    public void Search(string path, string name)
    {
        Thread th = new Thread(s => SearchThread(path, name));
        th.Start();
    }

    private void SearchThread(string path, string name)
    {
        try
        {
            _Search(path, name);
        }
        finally
        {
            callback.SearchEnd();
            if (stopSearch)
            {
                callback.InfoLabel("Search Cancelled", InfoState.Info);
                stopSearch = false;
            }
            else
                callback.InfoLabel("Search Done.", InfoState.Done);
        }
    }

私はThread.Abort()代わりに使用しましたreturn

private void _Search(string path, string name)
    {
        if (stopSearch) Thread.CurrentThread.Abort();
        DirectoryInfo Roots = new DirectoryInfo(path);

        foreach (FileInfo file in Roots.GetFiles())
        {
            if (stopSearch) Thread.CurrentThread.Abort(); 
            if (file.Name.IndexOf(name, StringComparison.InvariantCultureIgnoreCase) > -1)
            {
                _File item = new _File();
                item.Name = file.Name;
                item.Size = file.Length;
                item.Path = file.FullName;
                callback.File(item);
            }
        }
        foreach (DirectoryInfo folder in Roots.GetDirectories())
        {
            if (stopSearch) Thread.CurrentThread.Abort();
            if (folder.Name.IndexOf(name, StringComparison.InvariantCultureIgnoreCase) > -1)
            {
                _Folder item = new _Folder();
                item.Name = folder.Name;
                item.Path = folder.FullName;
                callback.Folder(item);
            }
            _Search(folder.FullName, name);
        }
    }
于 2012-05-06T06:41:33.237 に答える