【问题标题】:Cancel a task that running on thread in ASP.NET MVC using C#使用 C# 取消在 ASP.NET MVC 中的线程上运行的任务
【发布时间】:2020-11-24 12:54:22
【问题描述】:

如何在后台运行此任务并且我的其他 Web 内容(服务器 API)应该可以工作?也可以在任何时候取消。因为我的服务器能够运行繁重的操作和多线程。

C#

[HttpPost]
[AsyncTimeout(30 * 60 * 1000)]
//ConnectionId show importing data on UI as progress bar using SignalRProgress.
//Path import file path for import some bulk data in background.
//cancellationToken to cancel task when user need.
public async Task<ActionResult> LongRunningTask(string ConnectionId, string Path, System.Threading.CancellationToken cancellationToken)
{
    CancellationToken disconnectedToken = Response.ClientDisconnectedToken;
    var source = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, disconnectedToken);

    string someResponse = "Empty";

    await Task.Run(() =>
    {
        foreach (var item in spec)
        {
            i++;
            try
            {
                if (source != null && source.IsCancellationRequested)
                {
                    //abort or cancel this thread and 

                    //custome method that add progress to an hub context
                    //update UI for task cancelation with how much importing is done
                    Utility.SignalRProgressEvent.SendProgress(ConnectionId, Message, DonePercentage);
                    break;
                }
                
                importedDetails = service.ImportData(item, source.Token);
            }
            catch (CustomException ex)
            {
                someResponse += what is the validation issue in which record;
            }
            catch (JsonSerializationException ex)
            {
                someResponse += which attribute have serialization error;
            }
            catch (Exception ex)
            {
                throw ex;
            }

            //update UI for how much import is done
            someResponse += information of errors/importedid/validaiton issue;
            Utility.SignalRProgressEvent.SendProgress(ConnectionId, Message, DonePercentage);
        }
    }, source.Token);

    return Json(someResponse, JsonRequestBehavior.AllowGet);
}

Javascript

/*Update progress bar*/
function ProgressBarModal(showHide) {
    if (showHide === 'show') {
        $('#mod-progress').modal('show');
        if (arguments.length >= 2) {
            var percentage = "0";
            if (arguments.length >= 3) {
                percentage = arguments[2]
                $('#ProgressMessage').width(percentage);
                if (percentage == "100%") {
                    ProgressBarModal();
                }
            }
            $('#progressBarTextMessage').text(arguments[1] + " " + percentage);
            window.progressBarActive = true;
        }
    } else {
        $('#mod-progress').modal('hide');
        window.progressBarActive = false;
    }
}

var xhr = undefined;

/*start  import*/
function StartImport() {
    xhr = $.ajax({
            type: 'POST',
            url: "@Url.Action("Import", "BulkOps")",
            data: data,
            async: true, //I want run progress bar using JS
            beforeSend: function () {
                ProgressBarModal('show');
            },
            success: function (data) {
                //import done
            },
            error: function (err) {
                //handle import failing 
            },
            complete: function (data) {
                //share import report if possible
            }
        });
});

/*Abort running import*/
function AbortImport() {
    xhr.abort("Task aborted by the user.");
});

是否有任何可能的解决方案来中止相同的任务?但服务器不应停留在同一个长时间运行的进程上。

提前致谢。

请忽略我过去的问题。我放弃了线程的想法。

我正在尝试取消我在进程之间的长时间运行的任务,这 当我们使用单线程时是可能的,但我想运行任何 在后台线程中长时间运行,因此我可以在我的 网络。

这是否可以取消或中止正在运行的线程 背景?

[HttpPost] [AsyncTimeout(30 * 60 * 1000)] //ConnectionId show
importing data on UI as progress bar using SignalRProgress. //Path
import file path for import some bulk data in background.
//cancellationToken to cancel task when user need. public ActionResult
LongRunningTask(string ConnectionId, string Path,
System.Threading.CancellationToken cancellationToken) {
    CancellationToken disconnectedToken = Response.ClientDisconnectedToken;
    var source = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken,
disconnectedToken);

    string someResponse = "Empty";
    Thread t = new Thread(() => {
        if (source != null && source.IsCancellationRequested || string.IsNullOrWhiteSpace(ConnectionId))
        {
            //abort or cancel this thread and 

            //custome method that add progress to an hub context
            //update UI for task cancelation with how much importing is done
            Utility.SignalRProgressEvent.SendProgress(ConnectionId, Message, DonePercentage);
        }

        //update UI for how much import is done
        someResponse += information of errors/importedid/validaiton issue;
        Utility.SignalRProgressEvent.SendProgress(ConnectionId, Message, DonePercentage);
    });

    t.Start();

    //How do i wait here with main thread until above thread complete.
    return Json(someResponse, JsonRequestBehavior.AllowGet); } 

附: 1 用任务更改上面的线程然后我的完整服务器卡住了 直到任务完成。

附: 2 将上面的线程设为后台,然后主线程将启动 该线程并完成此 ajax 调用。然后我无法取消 任务。

我需要一个解决方案,允许我运行从网络导入 进度条,应该可以在任何时候取消,也可以在任何其他 mvc 上取消 动作应该不会受到这个动作的太大影响。因为我的服务器是 能够运行繁重的操作和多线程。

【问题讨论】:

  • 你为什么用Thread而不是Task
  • 看看这个:What's wrong with using Thread.Abort。最重要的是,.NET Core 不支持此方法。
  • @PeterCsala 我试图在线程中运行我的导入,因为我想在导入期间运行我的服务器 api 和其他服务器任务。
  • @TheodorZoulias,不需要使用线程,我只是想通过后台导入实现取消。
  • 请不要改变问题的主要焦点。编辑应仅限于澄清和改进。如果您还有其他问题,请发布另一个问题。

标签: c# asp.net-mvc multithreading cancellation-token background-thread


【解决方案1】:

有几个选项。这主要假设您正在使用一项任务,正如您应该为后台操作所做的那样。

合作取消

即您正在运行的任何任务都需要经常检查取消令牌并在取消时中止处理。这假定任何耗时的外部调用也接受取消令牌。

让任务运行但忽略结果

在某些情况下,可以简单地关闭进度对话框并让任务在后台继续运行,而不考虑任何结果。这假设任务最终会完成,并且这样做不会产生副作用。

使用线程中止

有一个Thread.Abort()。但是有very good reasons not to use thread abort。它也在 .Net core 中被删除。

将操作移至单独的进程

这应该让您关闭进程,并避免Thread.Abort 的一些陷阱。这是一个相当麻烦的解决方案,但可能适用于运行时间很长的操作。

【讨论】:

  • 感谢您的反馈,您能否重新检查我的问题?运行其他服务器 API 或其他东西。
  • @Kishan Choudhary 您在从服务器返回之前明确等待任务,因此服务器在响应之前等待。您之前的示例刚刚开始后台工作并在完成之前返回。
猜你喜欢
  • 1970-01-01
  • 2019-12-02
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
  • 2012-03-29
  • 1970-01-01
  • 2022-07-11
  • 2014-01-19
相关资源
最近更新 更多