找到与NSRunLoop匹配的NSThread(需要修复Socket Rocket)

时间:2017-12-11 10:27:53

标签: objective-c multithreading websocket core-foundation

我正在为Socket Rocket中的竞争条件进行修复。 很久以前就报告过这个错误,但仍然没有修复。

一年多以前,我已经编写了一个破解API的修复程序(只能使用共享线程),并且这个代码在生产时成功运行(当有很多用户时根本没有崩溃)。

现在我想以这样的方式调整我的修补程序,它不会破坏SRWebSocket的API。 为此,我需要找到匹配NSThread原谅NSRunLoop。这是一对一的关系,但我找到一个可以帮助我的API有问题。

<小时/> PS。修复非常简单。在NSRunLoop上进行的每个操作都必须从相应的线程完成。没有NSRunLoop或CFRunLoop API that can be safely used from another thread. So I've added such API to SRRunLoopThread`:

- (void)scheduleBlock: (void(^)())block
{
    [self performSelector: @selector(_runBlock:)
                 onThread: self
               withObject: [block copy]
            waitUntilDone: NO];
}

- (void)_runBlock: (void(^)())block
{
    block();
}

并在NSRunLoop上完成某些事情的地方使用它。

此修复程序显示了我需要找到匹配的NSThread

注意documentations表明performSelector:onThread:withObject:waitUntilDone:是线程安全的

  

您可以使用此方法将消息传递到应用程序中的其他线程。

我必须再次强调NSRunLoop CFRunLoop API没有线程安全:

  

警告

     

NSRunLoop 类通常不被认为是线程安全的   它的方法只能在当前的上下文中调用   线。你永远不应该试着调用 NSRunLoop 的方法   对象在不同的​​线程中运行,因为这样做可能会导致   意想不到的结果。

由于NSRunLoop与通过public class CustomImageView extends ImageView { public static float radius = 25.0f; public CustomImageView(Context context) { super(context); } public CustomImageView(Context context, AttributeSet attrs) { super(context, attrs); } public CustomImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onDraw(Canvas canvas) { //float radius = 36.0f; Path clipPath = new Path(); RectF rect = new RectF(0, 0, this.getWidth(), this.getHeight()); clipPath.addRoundRect(rect, radius, radius, Path.Direction.CW); canvas.clipPath(clipPath); super.onDraw(canvas); }} 桥接到/从 <your package name.CustomImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/thumbimg" android:layout_marginTop="8dp" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:visibility="gone" /> 无关,所以它具有完全相同的弱点。 因此,如果文档没有说它是线程安全的API,那么它没有线程安全,我无法在该上下文中使用它(所以@DisableR提出的答案显然无效)。

1 个答案:

答案 0 :(得分:1)

您可以执行具有runloop的块而无需线程。 块将在与运行循环相关联的线程上异步执行。

CFRunLoopPerformBlock([myNSRunLoop getCFRunLoop], kCFRunLoopCommonModes, block);
CFRunLoopWakeUp([myNSRunLoop getCFRunLoop]);

以下是关于macOS Tiger上-performSelectorOnMainThread: NSThread方法的实现的讨论,该方法不可用,问题与您的问题非常相似: http://www.cocoabuilder.com/archive/cocoa/112261-cfrunlooptimer-firing-delay.html