Saya memiliki panggilan balik yang mungkin berasal dari utas apa pun. Ketika saya mendapatkan panggilan balik ini, maka saya ingin melakukan tugas tertentu di utas utama.
Apakah saya perlu memeriksa apakah saya sudah berada di utas utama - atau adakah hukuman dengan tidak melakukan pemeriksaan ini sebelum memanggil kode di bawah ini?
dispatch_async(dispatch_get_main_queue(), ^{
// do work here
});
Jawaban:
Tidak, Anda tidak perlu memeriksa apakah Anda sudah berada di utas utama. Dengan mengirimkan blok ke antrian utama, Anda hanya menjadwalkan blok yang akan dieksekusi secara seri pada utas utama, yang terjadi ketika run loop yang sesuai dijalankan.
Jika Anda sudah berada di utas utama, tingkah lakunya sama: blok dijadwalkan, dan dieksekusi ketika loop run dari utas utama dijalankan.
sumber
async
kembali ke antrian utama, itu akan dijalankan tetapi itu mungkin mengacaukan waktu yang diharapkan dari tindakan Anda . Seperti kode UI dalamviewDidLoad()
tidak berjalan sampai setelah tampilan pertama kali ditampilkan .Untuk kasus pengiriman asinkron yang Anda jelaskan di atas, Anda tidak perlu memeriksa apakah Anda berada di utas utama. Seperti yang ditunjukkan oleh Bavarious, ini hanya akan di-antri untuk dijalankan di utas utama.
Namun, jika Anda mencoba melakukan hal di atas menggunakan a
dispatch_sync()
dan panggilan balik Anda ada di utas utama, aplikasi Anda akan menemui jalan buntu pada saat itu. Saya menjelaskan ini dalam jawaban saya di sini , karena perilaku ini mengejutkan saya ketika bergerak beberapa kode dari-performSelectorOnMainThread:
. Seperti yang saya sebutkan di sana, saya membuat fungsi pembantu:yang akan menjalankan blok secara bersamaan pada utas utama jika metode yang Anda gunakan saat ini tidak pada utas utama, dan hanya menjalankan blok inline jika itu. Anda dapat menggunakan sintaks seperti berikut untuk menggunakan ini:
sumber
dispatch_set_specific()
akan membantu dalam kasus yang Anda jelaskan: stackoverflow.com/a/12806754/19679 .Seperti jawaban lain yang disebutkan, dispatch_async dari utas utama baik-baik saja.
Namun, tergantung pada kasus penggunaan Anda, ada efek samping yang dapat Anda anggap merugikan: karena blok dijadwalkan pada antrian, itu tidak akan dijalankan sampai kontrol kembali ke loop berjalan, yang akan memiliki efek menunda eksekusi blok Anda.
Sebagai contoh,
Akan dicetak:
Untuk alasan ini, jika Anda mengharapkan blok untuk mengeksekusi di antara NSLog luar, dispatch_async tidak akan membantu Anda.
sumber
Tidak, Anda tidak perlu memeriksa apakah Anda berada di utas utama. Inilah cara Anda melakukan ini di Swift:
Termasuk dalam fungsi standar dalam repo saya, lihat: https://github.com/goktugyil/EZSwiftExtensions
sumber