0

我在网上没有找到任何合适的答案,所以我在这里发布我的问题。

__block int test = 1;
dispatch_async(dispatch_get_main_queue(), ^{
    test = 2;
});
NSLog(@"%i",test);

此代码将导致控制台消息“1”。

__block NSString *test = @"no";
dispatch_async(dispatch_get_main_queue(), ^{
    test = @"yes";
});
NSLog(@"%@",test);

此代码将导致控制台消息“否”。

为什么会这样?我认为 __block 标识符应该解决这种情况下的所有问题。我的假设是复制了局部变量,并且块内的代码实际上并没有修改其自身之外的任何内容。

如何修改 dispatch_async 中的局部变量?

对不起,如果这是一个菜鸟问题。

4

3 回答 3

11

您正在异步调度到主队列。

dispatch_async执行块之前的返回(巧合)。

强调非确定性并发编程可以是:

请注意,您NSLog()有时可能会在非常蓝的月亮中看到新值。您可能永远不会在调试环境中看到它,但某些客户可能会在 3 年后在今天不存在的系统配置上遇到这种行为。

修理?

dispatch_sync()从而确保您的后台队列和主队列有效地充当效率较低的单个串行队列。

... 或者 ...

操作完成后,使用某种同步结构将消息从主队列传回本地队列。IE:

dispatch_async(otherQueue, ^{
     ... do something ...;
     dispatch_async(firstQueue, ^{
          done(calculatedValue);
     };
};
于 2013-05-18T16:57:12.460 回答
1

您正在异步调度设置测试,这意味着您的 NSLog 语句将在块之前触发。

您必须这样做,或者将其更改为 dispatch_sync。

__block NSString *test = @"no";
dispatch_async(dispatch_get_main_queue(), ^{
  test = @"yes";
  NSLog(@"%@",test);
});

如果您需要在后台线程上执行某些操作,然后将其弹回主线程,只需执行以下操作:

__block NSString *test = @"no";
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
   test = @"setting Testing in the background";
   NSLog(@"Printing from the background:%@",test);
   dispatch_async(dispatch_get_main_queue(), ^{
    test = @"Setting Test on the main thread";
    NSLog(@"Logging test on the main thread:%@",test);
   });
});
于 2013-05-18T17:01:12.710 回答
0

您正在调用 dispatch_async。尽管您正在主线程上执行代码,但仍然无法确定代码“test = @”yes” 是否在“NSLog(@"%@",test);" 代码之前执行。

如果您使用 dispatch_sync 它将像 expexted 一样工作。

于 2013-05-18T16:57:21.663 回答