1

I have the following problem:

I need to run a function search (depth x) that basically searches a decision tree until a certain depth and then returns (or leaves in a class member) a value of type Move. At the same time I would like to be able to "cancel" the execution of the search if it goes on for too long.

It is also important that I don't have to wait for it if the search does finish faster. I realize this is not a complicated but I am not really familiar with C# concurrency controls.

5
  • 9
    and the code you've tried thus far is...? Commented Feb 23, 2015 at 11:37
  • At the moment my code exists for doing this without a timer, I am not sure how to modify this to have the option of early termination. Commented Feb 23, 2015 at 11:46
  • 2
    Could you share your piece of code with us? Commented Feb 23, 2015 at 11:57
  • Cancel an Async Task or a List of Tasks (C# and Visual Basic) Commented Feb 23, 2015 at 13:35
  • Both the backgroundworker and Task async implementations support cancellation (though by different approaches, one by bool and other by token). I suggest using Task as it is a newer approach. Commented Feb 23, 2015 at 14:15

2 Answers 2

1

Here is a simple example as starting point:

public class Runner
{
    private Task<int> search(CancellationToken ct)
    {
        var t_work = Task.Factory.StartNew<int>(() =>
        {
            int k = 0;

            while (k < 1000)
            {
                if (ct.IsCancellationRequested)
                {
                    return -1;
                }                    
                k += r.Next(200);
                Thread.Sleep(300);
            }
            return k;

        }, ct);
        return t_work;
    }

    Random r = new Random();

    public async Task SearchAsync()
    {
        var timeout = TimeSpan.FromSeconds(3);
        var cts = new CancellationTokenSource(timeout);
        var ct = cts.Token;
        var searchValue = await search(ct);
        string result = (searchValue < 0) ?
            "Search aborted without results" : "search value is: " + searchValue.ToString();
        Console.WriteLine(result);
    }
}

you can use it in a console app like this:

Console.WriteLine("test");
var r = new Runner();
r.SearchAsync().Wait();
r.SearchAsync().Wait();
r.SearchAsync().Wait();
r.SearchAsync().Wait();
Console.WriteLine("done..");
Sign up to request clarification or add additional context in comments.

1 Comment

why the downvote ? It is a mini example of a timed c# function as was asked.
0

I would use a Task for this, as it has built in mechanisms to handle errors, cancellation, and running Continuation Tasks when the task completes.

Assuming a custom return type of Move which I think you implied in your question:

private Task<Move> _searchTask;
private CancellationTokenSource _searchCancellationTokenSrc;

Then on a button click or similar, kick off your task. This will return immediately, keeping your UI responsive:

private void StartButton_Click(object sender, RoutedEventArgs e)
{
    _searchCancellationTokenSrc = new CancellationTokenSource();
    CancellationToken ct = _searchCancellationTokenSrc.Token;

    _searchTask = Task.Run(() =>
    {
         for (int i = 0; i < 10; i++ )
         {
             if(ct.IsCancellationRequested)
             {
                 // Clean up here
                 ct.ThrowIfCancellationRequested();
             }
             // Time consuming processing here
             Thread.Sleep(1000);
         }
         return new Move();
    },ct);

    _searchTask.ContinueWith((t) =>
    {
         Console.WriteLine("Canceled");
    }, TaskContinuationOptions.OnlyOnCanceled);

    _searchTask.ContinueWith((t) =>
    {
       Console.WriteLine("Faulted. t.Exception contains details of any exceptions thrown");               
    }, TaskContinuationOptions.OnlyOnFaulted);

    _searchTask.ContinueWith((t) =>
    {            
        Console.WriteLine("Completed t.Result contains your Move object");
    }, TaskContinuationOptions.OnlyOnRanToCompletion);
}

To cancel this, perhaps from another button:

 private void CancelButton_Click(object sender, RoutedEventArgs e)
 {
      _searchCancellationTokenSrc.Cancel();
 }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.