Introduction: I have a Server [WCF service library] and Client [Winform], client connects to server using netTcpBinding.
the server job is to share Computer Files to the client with a file manager features { New Folder,Move,Copy,Delete,Properties, Attributes and SEARCH }.
The Problem :
the search function is a recursive function, it adds item to client ListView instantly (using client CALLBACK) when it finds a (folder/file) name that contains the search key.
so it was all working perfect, until I added a stop search button, which suppose to allow the user to stop the recursive function _Search(), what happens when I try to stop searching is freezing the GUI and never get back from freezing mode till I "STOP Debugging".
In fact when I set points to see what's wrong with the search function in debugging mode, it works and the search stops.
This's the Code I use for searching:
WCF lib Side:
[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 Interface:
[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();
}
Client side :
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);
}
Client 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;
}
}
I'm really confused about fixing it, I'm not sure if I did choose the right title for my question ,so if that's happening because I need an Async callback, how would I convert my search function and Async Callback with WCF?