我们的应用程序使用TPL来序列化(可能)长时间运行的工作单元.工作(任务)的创建是用户驱动的,可以随时取消.为了拥有响应式用户界面,如果不再需要当前的工作,我们想放弃我们正在做的事情,并立即开始另一项任务.
任务排队等同于:
private Task workQueue;
private void DoWorkAsync
(Action<WorkCompletedEventArgs> callback, CancellationToken token)
{
if (workQueue == null)
{
workQueue = Task.Factory.StartWork
(() => DoWork(callback, token), token);
}
else
{
workQueue.ContinueWork(t => DoWork(callback, token), token);
}
}
Run Code Online (Sandbox Code Playgroud)
该DoWork方法包含长时间运行的呼叫,因此,token.IsCancellationRequested如果/当检测到取消时,它不会像不断检查状态和挽救一样简单.长时间运行的工作将阻止任务继续,直到它完成,即使任务被取消.
我已经提出了两个样本方法来解决这个问题,但我不相信这两种方法都是正确的.我创建了简单的控制台应用程序来演示它们如何工
需要注意的重要一点是,在原始任务完成之前会继续触发.
尝试#1:内部任务
static void Main(string[] args)
{
CancellationTokenSource cts = new CancellationTokenSource();
var token = cts.Token;
token.Register(() => Console.WriteLine("Token cancelled"));
// Initial work
var t = Task.Factory.StartNew(() =>
{
Console.WriteLine("Doing work");
// Wrap the long running …Run Code Online (Sandbox Code Playgroud) 我试图了解c ++中的取消点究竟是什么.我读过了:
但我在某些方面仍然有点困惑.例如,我正在使用文件write()函数.显然这是一个取消点.因此,当我调用write()时,我可以看到另一个线程可能开始处理(所以我的代码从写入线程切换到另一个线程),这通常发生在写入缓冲区已满并需要在写入之前清空时()可以成功/完成.
但在我看来,这不是一个线程的取消,而只是一个临时的阻塞/暂停,并没有线程"清理"做...
所以我的问题是,取消点是否与"阻塞点"有关? - 他们真的是一回事,还是有些不同?对取消点的清晰"顶级"描述将非常有用.
如果 的一个任务gather引发异常,其他任务仍然可以继续。
嗯,这不完全是我需要的。我想区分致命的错误和需要取消所有剩余任务的错误,以及不是而是应该记录的错误,同时允许其他任务继续。
这是我实现这一点的失败尝试:
from asyncio import gather, get_event_loop, sleep
class ErrorThatShouldCancelOtherTasks(Exception):
pass
async def my_sleep(secs):
await sleep(secs)
if secs == 5:
raise ErrorThatShouldCancelOtherTasks('5 is forbidden!')
print(f'Slept for {secs}secs.')
async def main():
try:
sleepers = gather(*[my_sleep(secs) for secs in [2, 5, 7]])
await sleepers
except ErrorThatShouldCancelOtherTasks:
print('Fatal error; cancelling')
sleepers.cancel()
finally:
await sleep(5)
get_event_loop().run_until_complete(main())
Run Code Online (Sandbox Code Playgroud)
(finally await sleep这里是为了防止解释器立即关闭,这会自行取消所有任务)
奇怪的是,呼吁cancel在gather实际上并没有取消它!
PS C:\Users\m> .\AppData\Local\Programs\Python\Python368\python.exe .\wtf.py
Slept for 2secs.
Fatal error; cancelling
Slept for 7secs.
Run Code Online (Sandbox Code Playgroud)
我对这种行为感到非常惊讶,因为它似乎 …
在 C# 中,我对停止循环感兴趣Parallel.ForEachAsync(考虑和之间的差异StopBreak);因为Parallel.ForEach我可以执行以下操作:
Parallel.ForEach(items, (item, state) =>
{
if (cancellationToken.IsCancellationRequested)
{
state.Stop();
return;
}
// some process on the item
Process(item);
});
Run Code Online (Sandbox Code Playgroud)
但是,由于我有一个需要异步执行的进程,所以我切换到了Parallel.ForEachAsync. ForEachAsync没有该方法Stop(),我可以按break如下方式循环,但我想知道这是否是打破循环的最有效方法(换句话说,循环在收到取消时需要尽快停止要求)。
await Parallel.ForEachAsync(items, async (item, state) =>
{
if (cancellationToken.IsCancellationRequested)
{
return;
}
// some async process on the item
await ProcessAsync(item);
});
Run Code Online (Sandbox Code Playgroud) c# asynchronous cancellation parallel.foreach parallel.foreachasync
Abortcontroller 信号不适用于 React 中的 Axios。
我想用 AbortController 替换 CancelToken (因为它已被弃用),但它不起作用,分别是请求没有被取消。
let testController: AbortController;
function loadTest() {
testController = new AbortController();
TestAPI.getTest(testController.signal)
.then((e) => {
console.log(e.data);
})
.catch((e) => {
console.error(e);
});
}
Run Code Online (Sandbox Code Playgroud)
同样在 UseEffect Cleanup 中,我执行了此操作(这里应该取消),并且信号的状态也设置为中止,但请求仍然没有取消:
useEffect(() => () => {
if (testController) testController.abort();
// console.log(testController.signal.aborted) => **true**
}, []);
Run Code Online (Sandbox Code Playgroud)
这是我的 API,我将 AbortSignal 传递给请求:
getTest(signal?: AbortSignal): Promise<AxiosResponse<Test[]>> {
return axios.get(`${URI}/test`, { signal });
},
Run Code Online (Sandbox Code Playgroud)
使用 Axios.CancelToken.source 时工作正常,但现在使用 AbortController,请求永远不会被取消。
使用:“axios”:“^ 0.26.0 ”,
有人设法将 AbortController 与 React 和 Axios 集成吗?或者 AbortController只 …
cancellation cancellationtokensource reactjs react-native axios
如果被调用的函数pthread_create具有以下结构
try{
...code....
pthread_detach(pthread_self());
pthread_exit(NULL);
}catch(...){
std::cout<<"I am here"<<std::endl;
}
Run Code Online (Sandbox Code Playgroud)
为什么省略号的异常处理程序在执行时被调用pthread_exit?(请注意std::exception,例如,不会抛出)
因此,我需要以编程方式停止在Sidekiq(3.1.2)中运行的作业,而不是预定的作业.我确实阅读了API文档,但没有找到任何关于取消正在运行的作业的信息.这可能与sidekiq有关吗?
当这不可能直接实现时,我的想法是绕过这个,通过在调用信号时在作业中引发异常,然后从重试集中删除作业.这显然不是最佳选择.
提前致谢
我在我的应用程序中使用这样的改造
final OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.interceptors().add(new YourInterceptor());
final OkClient okClient = new OkClient(okHttpClient);
Builder restAdapterBuilder = new RestAdapter.Builder();
restAdapterBuilder.setClient(okClient).setLogLevel(LogLevel.FULL)
.setEndpoint("some url");
final RestAdapter restAdapter = restAdapterBuilder.build();
public class YourInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
// TODO Auto-generated method stub
Request request = chain.request();
if (request != null) {
Request.Builder signedRequestBuilder = request.newBuilder();
signedRequestBuilder.tag("taggiventorequest");
request = signedRequestBuilder.build();
request.tag();
}
return chain.proceed(request);
}
}
Run Code Online (Sandbox Code Playgroud)
发送请求后我打电话
okHttpClient.cancel("taggiventorequest");
Run Code Online (Sandbox Code Playgroud)
但请求没有取消我收到改造的回复不知道为什么它没有取消我的请求
我需要排球,比如取消改造
https://github.com/promises-aplus/cancellation-spec上最早的问题是(在撰写本文时)9个月之前.我真的找不到关于"标准"承诺的取消功能的可靠信息来源.
到目前为止看起来这个功能是在bluebird中实现的,但作为一个库开发人员,我不想让我的包与完整的promise实现混乱.
我想做的只是传递一个承诺,并支持取消规范.
我在哪里可以找到这些信息?
我编写了以下MVC控制器来测试取消功能:
class MyController : Controller
{
[HttpGet("api/CancelTest")]
async Task<IActionResult> Get()
{
await Task.Delay(1000);
CancellationToken token = HttpContext.RequestAborted;
bool cancelled = token.IsCancellationRequested;
logger.LogDebug(cancelled.ToString());
return Ok();
}
}
Run Code Online (Sandbox Code Playgroud)
说,我想取消请求,因此在上面的控制器操作中记录值' true '.如果服务器实现IHttpRequestLifetimeFeature,这可能是服务器端.幸运的是,Kestrel确实如此,这可以通过以下方式实现:
var feature = (IHttpRequestLifetimeFeature) HttpContext.Features[typeof(IHttpRequestLifetimeFeature)];
feature.Abort();
Run Code Online (Sandbox Code Playgroud)
但问题是我想在客户端取消请求.例如,在浏览器中.在ASP.NET MVC/WebApi的预核版本中,如果浏览器中止请求,则取消令牌将自动取消.示例:在Chrome中多次刷新页面.在chrome dev工具的"网络"选项卡中,您现在可以看到取消上一个(未完成的)请求.
问题是:在Kestrel上运行的ASP.NET Core中,我只能在日志中看到以下条目:
Microsoft.AspNetCore.Server.Kestrel.Internal.Networking.UvException:错误-4081 ECANCELED操作已取消
因此,来自浏览器的中止请求到达并由Kestrel网络服务器处理.但它不会影响控制器中HttpContext的RequestAborted属性,因为该方法仍会记录值' false '.
问题: 有没有办法中止/取消我的控制器方法,以便将HttpContext.RequestAborted属性标记为已取消?
也许我可以做一些订阅Kestrel的操作取消触发器并调用IHttpRequestLifetimeFeature.Abort()方法的东西?
更新: 我做了一些进一步的测试,看起来HttpRequest IS实际上已经中止,但在实际取消之前似乎有某种延迟.延迟不是时间因素,似乎直接来自libuv(Kestrel网络服务器构建在其上的库).我在https://github.com/aspnet/KestrelHttpServer/issues/1103上发布了更多信息
更多更新: 问题已移至另一个,因为前一个包含多个问题.https://github.com/aspnet/KestrelHttpServer/issues/1139
cancellation asp.net-core-mvc kestrel-http-server asp.net-core
cancellation ×10
c# ×2
c++ ×2
exception ×2
android ×1
asp.net-core ×1
asynchronous ×1
axios ×1
ecmascript-6 ×1
httprequest ×1
javascript ×1
jobs ×1
okhttp ×1
promise ×1
pthreads ×1
python ×1
python-3.x ×1
react-native ×1
reactjs ×1
retrofit ×1
sidekiq ×1