2011-11-22 7 views
6

Tôi đang hiển thị một bảng với một số dữ liệu cho người dùng. Ngay sau khi xem được trình bày, tôi đang thực hiện cuộc gọi web để xem liệu có dữ liệu cập nhật (không đồng bộ) hay không. Khi cuộc gọi dịch vụ trả về, tôi muốn cập nhật dữ liệu cốt lõi của mình và chế độ xem.CoreData: cập nhật trong nền và đọc trong chủ đề chính gây ra khóa chết

Thật không may, tôi thường bị khóa chết vì chế độ xem đọc dữ liệu giống như cuộc gọi dịch vụ viết. Làm sao tôi có thể giải quyết việc này?

Khi tôi tạm dừng mô phỏng càng sớm càng nó bị đóng băng, các chủ đề chờ đợi đang chờ đợi tại các địa điểm sau:

nền (cập nhật) chủ đề: (psynch_cvwait)

[mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) 
           withObject:notification 
          waitUntilDone:YES]; 

chủ đề chính: (psynch_mutexwait) thực hiện một filteredArrayUsingPredicate

Cảm ơn rất nhiều!

+0

Cảm giác với tôi, từ văn bản giới thiệu, rằng bạn đang phá vỡ mô hình MVC. Chỉ nên có một đối tượng kiểm soát dữ liệu và tìm nạp dữ liệu đó. Quan điểm nên nói chuyện với người điều khiển nói chuyện với người mẫu. Không có bế tắc nếu chỉ có một đối tượng gọi các cuộc gọi không đồng bộ. Đó chỉ là linh cảm thôi. – simonpie

+0

Tôi không hiểu ... Tôi chỉ có một ViewController; khung nhìn yêu cầu bộ điều khiển này cho dữ liệu (thực hiện một 'filterArrayUsingPredicate'). Cùng ViewController bắt đầu một cuộc gọi dịch vụ web không đồng bộ (viewWillAppear), sau khi trả về, ghi dữ liệu vào cơ sở dữ liệu. Vì vậy, tôi chỉ có một đối tượng thực hiện các cuộc gọi async, nhưng tôi vẫn nhận được một bế tắc. – swalkner

+0

Bạn đã bao giờ tìm ra giải pháp thực tế cho vấn đề của mình chưa? Tôi đã có một tình huống tương tự (cuối cùng!) Bị mắc kẹt trong trình gỡ lỗi, nhưng tôi không chắc chắn nơi để đi từ đây ... – elsurudo

Trả lời

8

-mergeChangesFromContextDidSaveNotification: sẽ chặn chuỗi chính. Cuộc gọi đó sẽ khóa cả hai trường hợp NSManagedObjectContext trong khi nó cập nhật ngữ cảnh chính với các thay đổi được chuyển vào.

Điều này thường được xem là không thể tránh khỏi trong các ứng dụng trước iOS 5. Bạn có thể giảm thiểu nó bằng cách làm cho thường xuyên hơn, nhỏ hơn, tiết kiệm nhưng nó vẫn sẽ xảy ra.

Tùy chọn duy nhất khác cho các ứng dụng trước iOS 5 là nói ngữ cảnh chính với -reset: nhưng điều đó sẽ yêu cầu tìm nạp lại mọi thứ - một sự chậm trễ khác.

+0

và những gì có thể được thực hiện trong các ứng dụng iOS5? – swalkner

+0

Nếu nó là ứng dụng iOS 5.0 thuần túy thì có thể sử dụng ngữ cảnh mẹ/con để loại bỏ nhu cầu hợp nhấtThay đổi và xóa toàn bộ khối. –

+0

cách thức hoạt động? có một số hướng dẫn/tài liệu về việc xử lý ngữ cảnh cha/con này không? – swalkner

2

Dường như chủ đề chính đang cố gắng lấy một số khóa cấp thấp mà chủ đề nền đã có (hoặc ngược lại). Bạn đang sử dụng @synchronized ở đâu đó để cung cấp mutex?

Dù sao, có bất kỳ lý do nào khiến luồng nền của bạn cần đợi -mergeChangesFromContextDidSaveNotification: hoàn tất không? Nếu không, hãy vượt qua NO làm thông số cuối cùng.

+0

Tôi không sử dụng '@ synchroned' ... và chuyển' NO' sang ' -mergeChangesFromContextDidSaveNotification: 'không giúp được gì, thật không may:/ – swalkner

0

Tôi đã gặp sự cố tương tự (khóa trên psynch_cvwait) khi tôi đang hợp nhất các thay đổi ngữ cảnh (cả hai cách) giữa ngữ cảnh chính và ngữ cảnh nền (cả hai sử dụng NSConfinementConcurrencyType). Vấn đề là do đăng ký vào NSManagedObjectContextDidSaveNotification trên một hàng đợi khác nhau mà từ đó nó đã được gửi:

[[NSNotificationCenter defaultCenter] 
addObserverForName:NSManagedObjectContextDidSaveNotification 
object:mainContext 
queue:bgQueue 
usingBlock:^(NSNotification * _Nonnull note) { 
    // bgContext runs on bgQueue 
    [bgContext mergeChangesFromContextDidSaveNotification:note]; 
}] 

Kết quả là khối chưa từng được gọi, và cả hai hàng đợi chính và nền treo trên psynch_cvwait()

tôi cố định nó bằng cách không chặn hàng đợi của mainContext:

[[NSNotificationCenter defaultCenter] 
addObserverForName:NSManagedObjectContextDidSaveNotification 
object:mainContext 
queue:nil 
usingBlock:^(NSNotification * _Nonnull note) { 
    [bgQueue addOperationWithBlock:^{ 
     [bgContext mergeChangesFromContextDidSaveNotification:note]; 
    }]; 
}] 

Tuy nhiên, nó không có vẻ là vấn đề nếu tôi chặn hàng đợi nền khi hợp nhất thay đổi vào ngữ cảnh chính.