[英]How to stop a thread created with dispatch_async?
如果使用了太多时间(例如超过5分钟),我想强行停止dispatch_async
创建的线程。 通过互联网搜索,我发现有人认为无法停止该线程,有人知道吗?
在我的想象中,我想创建一个NSTimer
在指定的时间过去后停止线程。
+ (void)stopThread:(NSTimer*)timer
{
forcibly stop the thread???
}
+ (void)runScript:(NSString *)scriptFilePath
{
[NSTimer scheduledTimerWithTimeInterval:5*60 target:self selector:@selector(stopThread:) userInfo:nil repeats:NO];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[LuaBridge runLuaFile:scriptFilePath];
});
}
我的runLuaScript方法:
+ (void)runLuaFile:(NSString *)filePath
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
int error2 = luaL_dofile(L, [filePath fileSystemRepresentation]);
if (error2) {
fprintf(stderr, "%s", lua_tostring(L, -1));
lua_pop(L, 1);
}
lua_close(L);
}
亲爱的@Martin R,我应该这样使用lstop吗?当我想停止线程时,只需调用stopLuaRunning
方法?
static lua_State *L = NULL;
+ (void)runLuaFile:(NSString *)filePath
{
L = luaL_newstate();
luaL_openlibs(L);
int error2 = luaL_dofile(L, [filePath fileSystemRepresentation]);
if (error2) {
fprintf(stderr, "%s", lua_tostring(L, -1));
lua_pop(L, 1);
}
lua_close(L);
}
+ (void)stopLuaRunning:(lua_State *L)
{
lua_sethook(L, NULL, 0, 0);
luaL_error(L, "interrupted!");
}
您应该使用NSOperation
和NSOperationQueue
因为它们内置了对取消的支持,因此您的操作可以检查它是否被取消,并且您的计时器仅调用该操作的cancel
。
您无法杀死正在运行的块。 您必须以异步工作且可以取消的方式来实现runLuaFile
。
例如,如果运行脚本是通过NSTask
完成的,则可以在运行时间太长的情况下使用terminate
该任务。
NSOperation
可能无济于事,因为cancel
依赖于该操作是“合作的”:该操作必须定期检查是否已取消。 这不会停止正在运行的runLuaFile
方法。
更新:通过检查Lua解释器的源代码“ lua.c”,在我看来,您可以使用lua_sethook
取消正在运行的脚本。
一个非常简单的实现(对Lua状态使用静态变量)将是:
static lua_State *L = NULL;
+ (void)runLuaFile:(NSString *)filePath
{
L = luaL_newstate();
luaL_openlibs(L);
int error2 = luaL_dofile(L, [filePath fileSystemRepresentation]);
if (error2) {
fprintf(stderr, "%s", lua_tostring(L, -1));
lua_pop(L, 1);
}
lua_close(L);
L = NULL;
}
static void lstop (lua_State *L, lua_Debug *ar)
{
lua_sethook(L, NULL, 0, 0);
luaL_error(L, "interrupted!");
}
+ (void)stopLuaRunning
{
if (L != NULL)
lua_sethook(L, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
}
一个更优雅的解决方案是使用将Lua状态存储在类的实例变量中,并使runLuaFile
和stopLuaRunning
实例方法代替类方法。
通过互联网搜索,尽管没有办法阻止线程,但我得到了一些,有人知道吗?
不要打扰 停下来不是你的。 如果您有对队列的引用,则可以调用dispatch_release
,它将在适当的时间被销毁,但是您不会对全局队列执行此操作。
杀死该线程只会杀死队列池中的线程,应被视为与未定义行为一样好。
如果要控制线程的生存期,请创建自己的线程并与其运行循环进行交互。 但是,请确保您的程序正常从其实现中返回-不要仅仅因为某些程序对您不起作用或永远不会返回而杀死它们。 Martin R提到了这种情况将如何发生-您的任务应该支持超时,取消操作,或者在任务变得混乱时停止自身的其他方法。
韦恩还提到了一个很好的中间立场。
使用NSOperation和NSOperationQueue。
这是一个很长但是很有帮助的指南。
http://www.raywenderlich.com/19788/how-to-use-nsoperations-and-nsoperationqueues
在这种情况下,您的要点是覆盖main的示例。
@interface MyLengthyOperation: NSOperation
@end
@implementation MyLengthyOperation
- (void)main {
// a lengthy operation
@autoreleasepool {
for (int i = 0 ; i < 10000 ; i++) {
// is this operation cancelled?
if (self.isCancelled)
break;
NSLog(@"%f", sqrt(i));
}
}
}
@end
注意循环中间的if(self.isCancelled)。
这是管理后台操作而不创建自己的线程并直接对其进行管理的“现代” iOS方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.