停止挂同步方法

Pix*_*xar 1 c# multithreading asynchronous task cancellation

XenAPI 中有一个方法HTTP_actions.put_import() ,它是同步的,并且支持通过其 delegate 取消

我有以下方法:

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

在某些情况下,该方法HTTP_actions.put_import会挂起并且不会对isTaskCancelled(). 在这种情况下,整个应用程序也会挂起。

我可以在单独的线程中运行此方法,并在收到取消信号后强制终止它,但此方法并不总是挂起,有时我想优雅地取消此方法。只有当这个方法真的悬了的时候,我才想亲手杀死它。

处理这种情况的最佳方法是什么?

Pra*_*ana 5

为以下内容撰写博客文章:http://pranayamr.blogspot.in/2017/12/abortcancel-task.html

自过去 2 小时以来为您尝试了很多解决方案,我想出了以下可行的解决方案,请尝试一下

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();   
    }
}
Run Code Online (Sandbox Code Playgroud)