আইওএস 6 এ ব্লকটি সম্পূর্ণ করার জন্য প্রেরণ_গেট_কন্টেন_কিউ () এর বিকল্প?


101

আমার একটি পদ্ধতি আছে যা একটি ব্লক এবং একটি সমাপ্তি ব্লক গ্রহণ করে। প্রথম ব্লকটি পটভূমিতে চলতে হবে এবং সম্পূর্ণকরণ ব্লকটি যে পদ্ধতিতে বলা হয়েছিল তা সরিয়ে নেওয়া উচিত।

পরবর্তী সময়ের জন্য আমি সর্বদা ব্যবহার করেছিলাম dispatch_get_current_queue()তবে মনে হয় এটি আইওএস 6 বা ততোধিকের থেকে অবচয় হয়ে গেছে। পরিবর্তে আমার কী ব্যবহার করা উচিত?


আপনি কেন বলছেন dispatch_get_current_queue()যে আইওএস 6 এ অবহেলা করা হয়েছে? দস্তাবেজগুলি এ সম্পর্কে কিছুই বলে না
jere

3
সংকলক এটি সম্পর্কে অভিযোগ। চেষ্টা করে দেখুন
সিফিশার

4
@ জেডার শিরোনামের ফাইলটি পরীক্ষা করে দেখুন, এটি বর্ণনা করে যে এটি চিত্রিত হয়েছে
ডাব্লুডিইউ

সেরা অনুশীলন কী তা নিয়ে আলোচনা বাদে আমি [এনএসওপরেশনকুইউ কারেন্ট কিউইউ] দেখছি যা প্রশ্নের উত্তর দিতে পারে। এর ব্যবহার সম্পর্কে সতর্কতা সম্পর্কে নিশ্চিত নয়।
ম্যাট

ক্যাভিয়েট পাওয়া গেছে ------ [এনএসওপরেশনকুইউ কিউইউ কিউ] প্রেরণ_জেট_কন্টেনার_কিউ () হিসাবে সমান নয় ----- এটি কখনও কখনও শূন্য হয় ---- প্রেরণ_কেন্দ্র (প্রেরণ_গঠন_গ্লোবাল_কুই (0, 0), {S এনএসলগ (@ "কিউ (0, 0) হ'ল% @ ", প্রেরণ_সামগ্রী_কোয়ার_কিউ ()); এনএসএলগ (@" সিকিউ (0,0)% @ ", [এনএসওরেশনকুইউ কারেন্ট কিউ]];}); ----- কিউ (0,0) হ'ল <ওএস_ডিস্পপ্যাচ_কিউ_রূট: com.apple.root.default-qos [0x100195140]> সিকিউ (0,0) হ'ল (নাল) ----- চিত্রিত বা না প্রেরণ_জেট_কন্টেন_উইউ () বলে মনে হচ্ছে সকল অবস্থাতেই বর্তমান
সারিটি

উত্তর:


64

"কলার যে কাতারে ছিল তার উপর চালান" এর ধরণটি আবেদনময়ী, তবে শেষ পর্যন্ত এটি দুর্দান্ত ধারণা নয়। এই সারিটি নিম্ন অগ্রাধিকারের সারি, মূল সারি বা বিজোড় বৈশিষ্ট্যযুক্ত কিছু অন্যান্য সারি হতে পারে।

এটি সম্পর্কে আমার প্রিয় পদ্ধতির বক্তব্যটি হল "সমাপ্তি ব্লকটি এই বৈশিষ্ট্যগুলির সাথে একটি বাস্তবায়ন সংজ্ঞায়িত কাতারে চলে: x, y, z", এবং কলার যদি এর চেয়ে আরও নিয়ন্ত্রণ চায় তবে নির্দিষ্ট কাতারে ব্লকটি প্রেরণ করতে দিন। নির্দিষ্ট করার জন্য বৈশিষ্ট্যের একটি নির্দিষ্ট সেট হ'ল সিরিয়াল, অ-প্রেরণকারী এবং অন্য কোনও অ্যাপ্লিকেশন-দৃশ্যমান সারিতে সম্মতি সহ অ্যাসিঙ্ক "something

** সম্পাদনা করুন **

ক্যাটফিশ_মান নীচের মন্তব্যে একটি উদাহরণ রেখেছিলেন, আমি কেবল তার উত্তরে এটি যুক্ত করছি।

- (void) aMethodWithCompletionBlock:(dispatch_block_t)completionHandler     
{ 
    dispatch_async(self.workQueue, ^{ 
        [self doSomeWork]; 
        dispatch_async(self.callbackQueue, completionHandler); 
    } 
}

7
সম্পূর্ণ একমত. আপনি দেখতে পাচ্ছেন অ্যাপল সর্বদা এটি অনুসরণ করে; আপনি যখনই মূল কাতারে কিছু করতে চান তখন আপনাকে সর্বদা প্রধান কাতারে প্রেরণ করা প্রয়োজন কারণ অ্যাপল সর্বদা গ্যারান্টি দেয় যে আপনি আলাদা থ্রেডে আছেন। বেশিরভাগ সময় আপনি দীর্ঘ সময় চলমান প্রক্রিয়াটির জন্য ডেটা আনার / হেরফেরের কাজ শেষ করার অপেক্ষায় থাকেন এবং তারপরে আপনি এটিকে আপনার সমাপ্তি ব্লকের ঠিক পটভূমিতে প্রক্রিয়া করতে পারেন এবং তারপরে কেবল মূল সারিটির প্রেরণ ব্লকে কেবল ইউআই কলগুলি আটকে রাখতে পারেন। প্লাস প্রত্যাশার ক্ষেত্রে অ্যাপল যা সেট সেট করে তা অনুসরণ করা সর্বদা ভাল, যেহেতু বিকাশকারীরা প্যাটার্নে অভ্যস্ত হবে।
জ্যাক লরেন্স

1
দুর্দান্ত উত্তর .. তবে আপনি কী বলছেন তা
বোঝানোর

3
- (অকার্যকর) aMethodWithCompletionBlock: (dispatch_block_t) completionHandler {dispatch_async (self.workQueue, ^ {[স্ব doSomeWork]; dispatch_async (self.callbackQueue, completionHandler);}}
Catfish_Man

(সম্পূর্ণরূপে তুচ্ছ উদাহরণের জন্য)
Catfish_Man

3
এটি সাধারণ ক্ষেত্রে সম্ভব নয় কারণ এটি (এবং সত্যই সম্ভবত সম্ভাব্য) একযোগে একাধিক কাতারে থাকা, ডিসপ্যাচ_সেনসি () এবং প্রেরণ_সেট_টারেট_কিউ () এর কারণে। জেনারেল কেসের কিছু সাবসেট রয়েছে যা সম্ভব।
ক্যাটফিশ_মান

27

আপনি যে এপিআই গ্রহণের বর্ণনা দিচ্ছেন এটির জন্য এটি মূলত ভুল পদ্ধতি। যদি কোনও এআইপিআই চালুর জন্য কোনও ব্লক এবং একটি সমাপ্তি ব্লক গ্রহণ করে, নিম্নলিখিত তথ্যগুলি সত্য হওয়া দরকার:

  1. "চালানোর জন্য ব্লক" একটি অভ্যন্তরীণ কাতারে চালানো উচিত, উদাহরণস্বরূপ এমন একটি সারি যা এপিআই-র ব্যক্তিগত এবং তাই এটি সম্পূর্ণরূপে সেই এপিআই-র নিয়ন্ত্রণে। এর একমাত্র ব্যতিক্রম হ'ল যদি এপিআই নির্দিষ্টভাবে ঘোষণা করে যে ব্লকটি মূল কাতারে বা বিশ্বব্যাপী সমবর্তী সারিতে যে কোনও একটিতে চালিত হবে।

  2. সমাপ্তি ব্লকটি সর্বদা একটি টিউপল (সারি, ব্লক) হিসাবে প্রকাশ করা উচিত যদি না # 1 টির মতো একই অনুমানগুলি সত্য ধরে না রাখে, যেমন সমাপ্তি ব্লকটি একটি পরিচিত গ্লোবাল কাতারে চালিত হবে। সমাপ্তি ব্লকটি আরও পাস-ইন কাতারে অ্যাসিঙ্ক প্রেরণ করা উচিত।

এগুলি কেবল স্টাইলিস্টিক পয়েন্ট নয়, আপনার এপিআই যদি ডেডলকগুলি বা অন্য প্রান্ত-কেস আচরণ থেকে নিরাপদ থাকে যা অন্যথায় আপনাকে কোনও দিন নিকটতম গাছ থেকে ঝুলিয়ে রাখবে সেগুলি সম্পূর্ণ প্রয়োজনীয়। :-)


11
যুক্তিসঙ্গত বলে মনে হচ্ছে তবে কোনও কারণে এটি অ্যাপল তাদের নিজস্ব
এপিআইয়ের

2
সত্য, এবং আমার পূর্ববর্তী দৃ somewhat়তা কিছুটা সংশোধন করার জন্য, যদি এটি স্পষ্টভাবে স্পষ্ট হয় যে সমাপ্তি ব্লকটি মূল সারি বা বিশ্বব্যাপী সমবর্তী সারিতে চালিত হবে। আমি আমার উত্তরটি অনেকটা ইঙ্গিত করার জন্য পরিবর্তন করব।
jkh

অ্যাপল যে পদ্ধতি গ্রহণ করছে না সে সম্পর্কে মন্তব্য করতে: অ্যাপল সর্বদা সংজ্ঞা অনুসারে "সঠিক" হয় না। যথাযথ যুক্তিগুলি যে কোনও নির্দিষ্ট কর্তৃপক্ষের চেয়ে সর্বদা শক্তিশালী, যা কোনও বিজ্ঞানীই নিশ্চিত করবেন। আমি মনে করি উপরের উত্তরটি এটি একটি যথাযথ সফ্টওয়্যার আর্কিটেকচার দৃষ্টিকোণ থেকে খুব ভালভাবে বলেছে।
ওয়ার্নার আলটিউইচর

14

অন্য উত্তরগুলি দুর্দান্ত তবে আমার জন্য উত্তরটি কাঠামোগত। আমার সিঙ্গেলনের মতো একটি পদ্ধতি রয়েছে:

- (void) dispatchOnHighPriorityNonMainQueue:(simplest_block)block forceAsync:(BOOL)forceAsync {
    if (forceAsync || [NSThread isMainThread])
        dispatch_async_on_high_priority_queue(block);
    else
        block();
}

যার দুটি নির্ভরতা রয়েছে, যা:

static void dispatch_async_on_high_priority_queue(dispatch_block_t block) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), block);
}

এবং

typedef void (^simplest_block)(void); // also could use dispatch_block_t

এইভাবে আমি আমার কলগুলি অন্য থ্রেডে প্রেরণের জন্য কেন্দ্রীভূত করি।


12

আপনার dispatch_get_current_queueপ্রথমে আপনার ব্যবহার সম্পর্কে সতর্ক হওয়া উচিত । হেডার ফাইল থেকে:

শুধুমাত্র ডিবাগিং এবং লগিংয়ের জন্য প্রস্তাবিত:

কোডটি কিউর ফিরিয়ে নেওয়া সম্পর্কে কোনও অনুমান করা উচিত নয়, যদি না এটি বৈশ্বিক কাতারে একটি হয় বা কোড নিজেই তৈরি করে না। কোডটি ধরে নেওয়া উচিত নয় যে একটি সারিতে সিঙ্ক্রোনাস এক্সিকিউশনটি যদি ডিফল্ট_জেট_ক্রেনার_উইউ () দ্বারা ফিরে আসে না তবে সেই সারিটি লড থেকে নিরাপদ।

আপনি দুটি কাজের মধ্যে একটি করতে পারেন:

  1. আপনি মূলত পোস্ট করা কাতারে একটি রেফারেন্স রাখুন (আপনি যদি এটির মাধ্যমে তৈরি করেন dispatch_queue_create) এবং তখন থেকে এটি ব্যবহার করুন।

  2. এর মাধ্যমে সিস্টেম নির্ধারিত সারিগুলি ব্যবহার করুন dispatch_get_global_queueএবং আপনি কোনটি ব্যবহার করছেন তার একটি ট্র্যাক রাখুন।

আপনি যে কাতারে আছেন সে সম্পর্কে নজর রাখার জন্য পূর্বে সিস্টেমে নির্ভর করে কার্যকরভাবে, আপনাকে এটি নিজেই করতে হবে।


16
আমরা কোন সারিটি কী তা সন্ধানের dispatch_get_current_queue()জন্য ব্যবহার না করতে পারলে আমরা কীভাবে "আপনি মূলত পোস্ট করেছেন এমন কাতারে একটি রেফারেন্স রাখতে পারি" ? কখনও কখনও কোডটি কোন সারিটি চালু রয়েছে তা জানতে এটির কোনও নিয়ন্ত্রণ বা জ্ঞান থাকে না। আমার কাছে প্রচুর কোড রয়েছে যা (এবং হওয়া উচিত) একটি পটভূমির সারিতে কার্যকর করা যেতে পারে তবে মাঝে মাঝে গুই (অগ্রগতি বার, ইত্যাদি) আপডেট করতে হবে এবং সুতরাং সেই ক্রিয়াকলাপগুলির জন্য মূল সারিটিতে প্রেরণ_সইঙ্ক () প্রেরণ করতে হবে। যদি ইতিমধ্যে মূল কাতারে থাকে তবে dispatch_sync () চিরতরে লক হয়ে যাবে। এটির জন্য আমার কোডটি রিফ্যাক্টারে কয়েক মাস সময় লাগবে।
অভি বেকার্ট

3
আমি মনে করি যে এনএসআরএল সংযোগটি একই থ্রেডের কাছ থেকে ডেকে আনা হয়েছে তার সমাপ্তি কলব্যাক দেয়। কলব্যাকের সময় এটি ব্যবহার করার জন্য যে সারিটি কল করা হয়েছিল তা সংরক্ষণ করার জন্য কি এটি একই API "dispatch_get_current_queue" ব্যবহার করবে?
ত্রুটিযুক্ততা

5

অ্যাপল হ্রাস পেয়েছে dispatch_get_current_queue(), তবে অন্য জায়গায় একটি ছিদ্র রেখে গেছে, সুতরাং আমরা বর্তমান প্রেরণের সারি পেতে সক্ষম হয়েছি:

if let currentDispatch = OperationQueue.current?.underlyingQueue {
    print(currentDispatch)
    // Do stuff
}

এটি কমপক্ষে মূল সারিতে কাজ করে। দ্রষ্টব্য, এই underlyingQueueসম্পত্তি আইওএস 8 থেকে উপলব্ধ।

আপনার যদি মূল কাতারে সমাপ্তি ব্লকটি সম্পাদন করতে হয় তবে আপনি OperationQueueসরাসরি ব্যবহার করতেও পারেন , মানে জিসিডি ছাড়াই।



0

এটি আমারও উত্তর। সুতরাং আমি আমাদের ব্যবহারের ক্ষেত্রে সম্পর্কে কথা বলতে হবে।

আমাদের একটি পরিষেবাদি স্তর এবং ইউআই স্তর রয়েছে (অন্যান্য স্তরগুলির মধ্যে)। পরিষেবা স্তর ব্যাকগ্রাউন্ডে কাজগুলি চালায়। (ডেটা ম্যানিপুলেশন টাস্ক, কোরডাটা টাস্ক, নেটওয়ার্ক কল ইত্যাদি)। UI স্তরটির চাহিদা পূরণের জন্য পরিষেবা স্তরের কয়েকটি অপারেশন সারি রয়েছে।

ইউআই স্তরটি তার কাজটি করার জন্য পরিষেবা স্তরের উপর নির্ভর করে এবং তারপরে একটি সাফল্য সমাপ্তি ব্লক চালায়। এই ব্লকটিতে এটিতে ইউআইকিট কোড থাকতে পারে। একটি সাধারণ ব্যবহারের ক্ষেত্রে হ'ল সার্ভার থেকে সমস্ত বার্তা পাওয়া এবং সংগ্রহের দৃশ্যটি পুনরায় লোড করা।

এখানে আমরা গ্যারান্টি দিচ্ছি যে পরিষেবাগুলি স্তরে প্রবেশকারী ব্লকগুলি সেই সারিতে প্রেরণ করা হয়েছে যেখানে পরিষেবাটি চালু ছিল। যেহেতু dispatch_get_current_ueue একটি অবহ্রাসিত পদ্ধতি, তাই আমরা কলারের বর্তমান সারিটি পেতে NSOperationQueue.currentQueue ব্যবহার করি। এই সম্পত্তি সম্পর্কে গুরুত্বপূর্ণ নোট।

একটি চলমান অপারেশনের প্রসঙ্গের বাইরে থেকে এই পদ্ধতিটি কল করার ফলে সাধারণত ফিরে আসে না in

যেহেতু আমরা সর্বদা একটি পরিচিত সারিতে আমাদের পরিষেবাগুলি প্রার্থনা করি (আমাদের কাস্টম সারি এবং মূল সারি) এটি আমাদের পক্ষে ভাল কাজ করে। আমাদের ক্ষেত্রে কেস আছে যেখানে সার্ভিসএ পরিষেবা পরিষেবা কল করতে পারে সার্ভিস কল করতে পারে। যেহেতু প্রথম পরিষেবা কলটি কোথা থেকে আনা হচ্ছে তা আমরা নিয়ন্ত্রণ করি, তাই আমরা জানি যে বাকি পরিষেবাগুলি একই নিয়ম অনুসরণ করবে।

সুতরাং NSOperationQueue.currentQueue সর্বদা আমাদের ক্যু বা মেইনক্যুতে ফিরে আসবে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.