মূল থ্রেডে কার্য সম্পাদন করতে জিসিডি CD


254

আমার কাছে একটি কলব্যাক রয়েছে যা কোনও থ্রেড থেকে আসতে পারে। আমি যখন এই কলব্যাকটি পাব তখন আমি মূল থ্রেডে একটি নির্দিষ্ট কাজ সম্পাদন করতে চাই।

আমি কি ইতিমধ্যে মূল থ্রেডে আছি কিনা তা যাচাই করা দরকার - বা নীচে কোডটি কল করে বেফোরা এই চেকটি না করে কোনও জরিমানা আছে কি?

dispatch_async(dispatch_get_main_queue(), ^{
   // do work here
});

114
পাঁচ বছর পরে আমি এখনও জিসিডি ব্লকের সিনট্যাক্সটি মনে করতে পারি না এবং প্রতিবারেই এখানে শেষ করতে পারি।
স্পেসট্রকার

7
@ স্পেসট্রিকার - এটি একই কারণেই আমি এই পৃষ্ঠায় রয়েছি: ডি
ম্যাথু কওলি

4
9 বছর পরে, এবং আমি এখনও এই পৃষ্ঠা থেকে সিনট্যাক্স অনুলিপি করতে আসা।
ওসা

উত্তর:


152

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

আপনি যদি ইতিমধ্যে মূল থ্রেডে থাকেন তবে আচরণটি একই রকম: ব্লকটি নির্ধারিত হয় এবং মূল থ্রেডের রান লুপটি চালিত হলে কার্যকর করা হয় uted


3
প্রশ্ন ছিল যে "এই চেকটি না করে" জরিমানা আছে কি না ... ... আমি মনে করব যে অ্যাসিঙ্ক প্রেরণটি যখন প্রয়োজন হয় না তখন এটি ব্যবহারের জন্য একটি পারফরম্যান্স পেনাল্টি রয়েছে, বা এটি তুচ্ছ?
ড্যান রোজনস্টার্ক

1
@ ইয়ার আমি মনে করি না বেশিরভাগ ক্ষেত্রেই পারফরম্যান্সের লক্ষণীয় প্রভাব লক্ষ্য করা যায়: জিসিডি একটি লাইটওয়েট লাইব্রেরি। এটি বলেছিল, আমি এই প্রশ্নটি বুঝতে পেরেছিলাম: 'নীচের কোডটি দিয়েছি, আমি কি মূল থ্রেডে আছি কিনা তা খতিয়ে দেখার দরকার আছে?'

7
তবে আপনাকে অবশ্যই পরীক্ষা করা দরকার যে আপনি dispatch_sync ব্যবহার করেন কিনা। অন্যথায় আপনি একটি অচলাবস্থা পেতে।
ভিক্টর এঙ্গেল

যদি আপনি মূল কাতারে থাকেন এবং মূল কাতারে asyncফিরে প্রেরণ করেন তবে এটি চালানো হবে তবে এটি আপনার ক্রিয়াকলাপের প্রত্যাশিত সময়কে বিশৃঙ্খলা করতে পারে । এই ধরনের মধ্যে UI 'তে কোড হিসেবে viewDidLoad() পর্যন্ত চলমান না পরে দৃশ্য প্রথম প্রদর্শন করা হয়
pkamb

106

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

তবে আপনি যদি dispatch_sync()উপরেরটি ব্যবহার করার চেষ্টা করেন এবং যদি আপনার কলব্যাক মূল থ্রেডে থাকে তবে আপনার অ্যাপ্লিকেশনটি সেই সময়ে অচল হয়ে যাবে। আমি এখানে আমার উত্তরে এটি বর্ণনা করছি , কারণ কিছু কোড থেকে সরানোর সময় এই আচরণটি আমাকে অবাক করেছিল -performSelectorOnMainThread:। আমি যেমন এখানে উল্লেখ করেছি, আমি একটি সহায়ক ফাংশন তৈরি করেছি:

void runOnMainQueueWithoutDeadlocking(void (^block)(void))
{
    if ([NSThread isMainThread])
    {
        block();
    }
    else
    {
        dispatch_sync(dispatch_get_main_queue(), block);
    }
}

আপনি যে পদ্ধতিটি বর্তমানে রয়েছেন তা মূল থ্রেডে না থাকলে এটি মূল থ্রেডে সিঙ্ক্রোনিকভাবে একটি ব্লক চালাবে এবং যদি ব্লকটি ইনলাইন হয় তবে তা সম্পাদন করে। আপনি এটি ব্যবহার করতে নীচের মত বাক্য গঠনতে নিয়োগ করতে পারেন:

runOnMainQueueWithoutDeadlocking(^{
    //Do stuff
});

1
এটিকে "রানঅনমাইনকিউইউ সিঙ্ক" বলে কিছু বলছেন না কেন? এটি যে অচলাবস্থার সাথে সংঘবদ্ধ হতে পারে এবং না তা এই জাতীয় ধরণের জিনিস যা আমি আমার কোডগুলিতে রাখতে চাই না। ধন্যবাদ এবং সর্বদা হিসাবে +1।
ড্যান রোজনস্টার্ক

2
@ ইয়ার - আমি কেবল এটি নামটি দিয়েছি যাতে এটি আমার কাছে স্পষ্ট হয়ে যায় যে আমি কেন এই সহায়ক সহায়ক ফাংশনটি ব্যবহার না করে মূল কাতারে একযোগে ব্লকগুলি বন্ধ করছি না। এটা আমার কাছে মনে করিয়ে দেওয়ার মতো বিষয় ছিল।
ব্র্যাড লারসন

3
এই ফাংশনটি দিয়ে অচলাবস্থা এখনও সম্ভব। মেইন-সারি সিঙ্ক> অন্যান্য-সারি সিঙ্ক> প্রধান-সারিটি অচলাবস্থার হবে।
hfossli

2
@ hfossli - সত্য, এটি প্রতিটি ক্ষেত্রে পরিচালনা করবে না। আমার ব্যবহারে, আমি সবসময় হয় মূল থ্রেডে একটি ব্যাকগ্রাউন্ড সিরিয়াল কাতারে একটি অ্যাসিনক্রোনাস প্রেরণ থেকে কল করছিলাম বা। আমি ভাবছি যদি dispatch_set_specific()ক্ষেত্রে আপনি বর্ণনা সাহায্য হবে: stackoverflow.com/a/12806754/19679
ব্র্যাড লারসন

1
[এনএসটি গ্রেড ইজ মেইনথ্রেড] প্রায়শই হ্যাঁ ফেরত দেয় এবং জিসিডি প্রোগ্রামিংয়ে এই কেসটি পরীক্ষা করার জন্য নিরাপদ বলে বিবেচিত হয় না। stackoverflow.com/questions/14716334/...
উইল Larche

57

উল্লিখিত অন্যান্য উত্তরের হিসাবে, মূল থ্রেড থেকে প্রেরণ_অ্যাসেন্সিক ঠিক আছে।

যাইহোক, আপনার ব্যবহারের ক্ষেত্রে নির্ভর করে এমন একটি পার্শ্ব প্রতিক্রিয়া রয়েছে যা আপনি কোনও অসুবিধা বিবেচনা করতে পারেন: যেহেতু ব্লকটি একটি সারিতে নির্ধারিত হয়েছে, নিয়ন্ত্রণ রান রান লুপে ফিরে না যাওয়া পর্যন্ত এটি কার্যকর হবে না, যার ফলে বিলম্বের প্রভাব পড়বে আপনার ব্লকের কার্যকরকরণ

উদাহরণ স্বরূপ,

NSLog(@"before dispatch async");
dispatch_async(dispatch_get_main_queue(), ^{
    NSLog(@"inside dispatch async block main thread from main thread");
});
NSLog(@"after dispatch async");

প্রিন্ট আউট করবে:

before dispatch async
after dispatch async
inside dispatch async block main thread from main thread

এই কারণে, আপনি যদি এই ব্লকটি বহিরাগত এনএসলোগের মধ্যে অন্তর্নিহিত করার প্রত্যাশা করছিলেন, তবে প্রেরণ_কেন্দ্রিক আপনাকে সাহায্য করবে না।


এটি বিবেচনা করার জন্য এটি গুরুত্বপূর্ণ বিষয়টি বলার দরকার আছে
মার্ক-আলেকজান্দ্রে বারুব

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

1

না আপনি মূল থ্রেডে আছেন কিনা তা খতিয়ে দেখার দরকার নেই। আপনি সুইফটে কীভাবে এটি করতে পারেন তা এখানে:

runThisInMainThread { () -> Void in
    runThisInMainThread { () -> Void in
        // No problem
    }
}

func runThisInMainThread(block: dispatch_block_t) {
    dispatch_async(dispatch_get_main_queue(), block)
}

এটি আমার রেপোতে একটি স্ট্যান্ডার্ড ফাংশন হিসাবে অন্তর্ভুক্ত রয়েছে, এটি পরীক্ষা করে দেখুন: https://github.com/goktugyil/EZSwiftExtensions

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