如何停止与dispatch_async创建线程?(How to stop a thread crea

2019-10-18 09:04发布

我想强行停止创建线程dispatch_async如果使用了太多的时间,例如越过5分钟。 通过搜索在互联网上,我得到了一些人认为,没有办法阻止线程,没有任何一个知道吗?

在我的想象,我想创建一个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);
}

亲爱的@马丁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!");
}

Answer 1:

你不能杀死正在运行的块。 你必须实现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实例方法,而不是类的方法。



Answer 2:

您应该使用NSOperationNSOperationQueue ,因为他们已经内置支持取消使您的操作可以检查它是否取消,您的计时器只是要求cancel该操作。



Answer 3:

通过搜索在互联网上,我得到了一些人会想到有没有办法停止线程,没有任何一个知道吗?

不要打扰; 这是不是你停下来。 如果你有一个队列的引用,那么你可以调用dispatch_release ,它会在适当的时候被摧毁,但你不会与全局队列做到这一点。

杀死一个线程会杀了队列的池中的线程,并应被视为未定义行为一样好。

如果要控制线程的生命周期,创建你自己的线程,并与它的运行循环互动。 但确保您的程序在它们实现正常返回 - 不只是杀的东西,因为它不为你工作或不退还。 马丁·基R提及怎么会发生这种事 - 你的任务应该支持暂停,取消或其他手段来阻止自己在事件中的任务已经流氓。

北斗星的也提到了一个很好的中间地带。



Answer 4:

使用的NSOperation和NSOperationQueue。

这是一个漫长的,但有益的指导。

http://www.raywenderlich.com/19788/how-to-use-nsoperations-and-nsoperationqueues

在这种情况下,关键点对你来说,是有例如覆盖主要的。

@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

请注意,如果(self.isCancelled)在循环的中间。

这是管理的后台操作,而无需创建你自己的线程,并将它们直接管理的“现代”的iOS方式。



文章来源: How to stop a thread created with dispatch_async?