繁体   English   中英

如何停止使用dispatch_async创建的线程?

[英]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!");
}

您应该使用NSOperationNSOperationQueue因为它们内置了对取消的支持,因此您的操作可以检查它是否被取消,并且您的计时器仅调用该操作的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状态存储在类的实例变量中,并使runLuaFilestopLuaRunning实例方法代替类方法。

通过互联网搜索,尽管没有办法阻止线程,但我得到了一些,有人知道吗?

不要打扰 停下来不是你的。 如果您有对队列的引用,则可以调用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM