Multithreading cancellation

  • Thread starter Thread starter airwot4
  • Start date Start date
A

airwot4

I have the below code for a multithreaded winforms application. It
works successfully apart from the cancel function.

AppendLog2 has an out parameter which should return true if either of
two conditions are met (to cancel operation). This parameter is not
being passed back when AppendLog2 invokes itself, which is everytime
due to the operation.

Any ideas how I could better accomplish this? I followed this article:
http://msdn.microsoft.com/en-us/library/ms951109.aspx

Thanks



private void btnFSearch_Click_1(object sender, EventArgs e)
{
//Starts search operation or cancels running operation
....
switch (_state)
{
case RunState.Idle:
_state = RunState.Running;
btnFSearch.Text = "Cancel";

FSearchDeleteDelegate delMain = new
FSearchDeleteDelegate(FileExistsLoop);
delMain.BeginInvoke(arComputers, txtFSearch.Text, null, null);
break;

case RunState.Running:
_state = RunState.Cancelled;
btnFSearch.Enabled = false;
break;

case RunState.Cancelled:
MessageBox.Show("Operation currently cancelling");
break;
}
}

public void FileExistsLoop(ArrayList arComputers, string
strFileSearchPath)
{
//Loops through arComputers and logs back to main UI.
bool cancel = false;
AppendLog2("Checking existance of " + strFileSearchPath + " on " +
arComputers.Count + " computers.", out cancel);
foreach (string strComputer in arComputers)
{
if (cancel) break;
if (Functions.PingTest(strComputer))
{
if (Functions.FileExists(strComputer, strFileSearchPath))
AppendLog2(strComputer + " = file exists", out cancel);
else
AppendLog2(strComputer + " = file not found", out cancel);
}
else
AppendLog2(strComputer + " is not responding to ping requests",
out cancel);
}
AppendLog2("***Finished***", out cancel);
}

public void AppendLog2(string log, out bool cancel)
{
if (txtOutput.InvokeRequired)
{
LogDelegate2 delInstance = new LogDelegate2(AppendLog2);
object inoutCancel = false;

Invoke(delInstance, new object[] { log, inoutCancel });

cancel = (bool)inoutCancel;
}
else
{
//Check for cancel
cancel = (_state == RunState.Cancelled);

// Check for completion
if (cancel || (log == "***Finished***"))
{
_state = RunState.Idle;
cancel = true;
...
}

...
}
return;
}
 
Personally I'd look at BackgroundWorker in this case, using CancelAsync
to request a cancel, with the worker code checking CancellationPending
to see if it should exit. This then handles all the grunge for you...

Marc
 
Well, its kind of convoluted to explain but your problem basically
lies on your boxing and un-boxing of the Boolean (value type)
variable.

You box when you call “object inoutCancel = false” you un-box when you
call the “public void AppendLog2(string log, out bool cancel)”
function etc.

I think you should do what Mark is suggesting but if you want to live
things the way they are you could at least change the Boolean cancel
variable to an object such as CancelEventArgs sot that you don’t have
to worry about boxing and un-boxing.

I hacked your exaple and made one of my own using CancelEventArgs so
that you can get the picture:

------------------------------

delegate void LogDelegate2(string log, CancelEventArgs cancel);

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();

new Thread(DoIt).Start();
}

void DoIt()
{
CancelEventArgs cancel = new CancelEventArgs();
AppendLog2("aaaa", cancel);
}

public void AppendLog2(string log, CancelEventArgs cancel)
{
if (this.InvokeRequired)
{
LogDelegate2 delInstance = new LogDelegate2(AppendLog2);
Invoke(delInstance, new object[] { log, cancel });

bool cancelVal = cancel.Cancel;
}
else
{
cancel.Cancel = true;
}

return;
}
}


I have the below code for a multithreaded winforms application. It
works successfully apart from the cancel function.

AppendLog2 has an out parameter which should return true if either of
two conditions are met (to cancel operation). This parameter is not
being passed back when AppendLog2 invokes itself, which is everytime
due to the operation.

Any ideas how I could better accomplish this? I followed this article:http://msdn.microsoft.com/en-us/library/ms951109.aspx

Thanks

private void btnFSearch_Click_1(object sender, EventArgs e)
{
//Starts search operation or cancels running operation
...
  switch (_state)
  {
    case RunState.Idle:
      _state = RunState.Running;
      btnFSearch.Text = "Cancel";

      FSearchDeleteDelegate delMain = new
FSearchDeleteDelegate(FileExistsLoop);
      delMain.BeginInvoke(arComputers, txtFSearch.Text, null, null);
      break;

    case RunState.Running:
      _state = RunState.Cancelled;
      btnFSearch.Enabled = false;
      break;

    case RunState.Cancelled:
      MessageBox.Show("Operation currently cancelling");
      break;
    }

}

public void FileExistsLoop(ArrayList arComputers, string
strFileSearchPath)
{
//Loops through arComputers and logs back to main UI.
  bool cancel = false;
  AppendLog2("Checking existance of " + strFileSearchPath + " on " +
arComputers.Count + " computers.", out cancel);
  foreach (string strComputer in arComputers)
  {
    if (cancel) break;
    if (Functions.PingTest(strComputer))
    {
      if (Functions.FileExists(strComputer, strFileSearchPath))
        AppendLog2(strComputer + " = file exists", out cancel);
      else
        AppendLog2(strComputer + " = file not found", out cancel);
    }
    else
      AppendLog2(strComputer + " is not responding to ping requests",
out cancel);
  }
  AppendLog2("***Finished***", out cancel);

}

public void AppendLog2(string log, out bool cancel)
{
  if (txtOutput.InvokeRequired)
  {
    LogDelegate2 delInstance = new LogDelegate2(AppendLog2);
    object inoutCancel = false;

    Invoke(delInstance, new object[] { log, inoutCancel });

    cancel = (bool)inoutCancel;
   }
   else
   {
      //Check for cancel
      cancel = (_state == RunState.Cancelled);

      // Check for completion
      if (cancel || (log == "***Finished***"))
      {
        _state = RunState.Idle;
        cancel = true;
        ...
      }

       ...
    }
  return;



}- Hide quoted text -

- Show quoted text -
 
Re boxing - actually, I suspect it relates more to not getting the value
back out of the array here:

object inoutCancel = false;
Invoke(delInstance, new object[] { log, inoutCancel });
cancel = (bool)inoutCancel;

But to be honest, until you posted I didn't look too much at the
specific code, preferring to lean towards a much simpler (and proven)
approach like BackgroundWorker ;-p

Marc
 
Ignore me - I misread the code anyways!

But it goes to show the point of using the simplest approach ;-p

Marc
 
But to be honest, until you posted I didn't look too much at the
specific code, preferring to lean towards a much simpler (and proven)
approach like BackgroundWorker ;-p

Yeah, post like this are real turn offs because they don’t compile and
are loooong so it’s hard to get someone to bother trying to figure
them out.

If only people posted “Short but complete examples”….. Oops, can I use
that phrase? Did Jon trade mark that already and I have to pay
royalties now?? :)
 
Thanks for the responses, I'll give BackgroundWorker a try instead.

And sorry about the long post, I should have cut it down!
 
Back
Top