Search code examples
c#multithreadingasynchronoustaskcancellation

Stop hanging synchronous method


There is a method HTTP_actions.put_import() in XenAPI, which is synchronous and it supports cancellation via its delegate.

I have the following method:

private void UploadImage(.., Func<bool> isTaskCancelled)
{
    try
    {
        HTTP_actions.put_import(
            cancellingDelegate: () => isTaskCancelled(),
            ...);
    }
    catch (HTTP.CancelledException exception)
    {
    }
}

It so happens that in some cases this method HTTP_actions.put_import hangs and doesn't react to isTaskCancelled(). In that case the whole application also hangs.

I can run this method in a separate thread and kill it forcefully once I receive cancellation signal, but this method doesn't always hang and sometimes I want to gracefully cancel this method. Only when this method is really hanging, I want to kill it myself.

What is the best way to handle such situation?


Solution

  • Wrote blog post for below : http://pranayamr.blogspot.in/2017/12/abortcancel-task.html

    Tried lot of solution since last 2 hr for you and I come up with below working solution , please have try it out

    class Program
    {
       //capture request running that , which need to be cancel in case
       // it take more time 
        static Thread threadToCancel = null;
        static async Task<string> DoWork(CancellationToken token)
        {
            var tcs = new TaskCompletionSource<string>();
            //enable this for your use
        //await Task.Factory.StartNew(() =>
        //{
        //    //Capture the thread
        //    threadToCancel = Thread.CurrentThread;
        //    HTTP_actions.put_import(...); 
        //});
        //tcs.SetResult("Completed");
        //return tcs.Task.Result;
    
        //comment this whole this is just used for testing 
            await Task.Factory.StartNew(() =>
            {
                //Capture the thread
                threadToCancel = Thread.CurrentThread;
    
                //Simulate work (usually from 3rd party code)
                for (int i = 0; i < 100000; i++)
                {
                    Console.WriteLine($"value {i}");
                }
    
                Console.WriteLine("Task finished!");
            });
    
            tcs.SetResult("Completed");
            return tcs.Task.Result;
        }
    
    
        public static void Main()
        {
            var source = new CancellationTokenSource();
            CancellationToken token = source.Token;
            DoWork(token);
            Task.Factory.StartNew(()=>
            {
                while(true)
                {
                    if (token.IsCancellationRequested && threadToCancel!=null)
                    {
                        threadToCancel.Abort();
                        Console.WriteLine("Thread aborted");
                    }
                }
            });
            ///here 1000 can be replace by miliseconds after which you want to 
            // abort thread which calling your long running method 
            source.CancelAfter(1000);
            Console.ReadLine();   
        }
    }