অপেক্ষা এবং চালিয়ে যাওয়ার সাথে পার্থক্য


119

কেউ ব্যাখ্যা করতে পারবেন যদি awaitএবং ContinueWithসমার্থক বা নিম্নলিখিত উদাহরণে নয়। আমি টিপিএল প্রথমবার ব্যবহার করার চেষ্টা করছি এবং সমস্ত নথিপত্র পড়ছি, তবে পার্থক্যটি বুঝতে পারছি না।

অপেক্ষায় :

String webText = await getWebPage(uri);
await parseData(webText);

চালিয়ে যান :

Task<String> webText = new Task<String>(() => getWebPage(uri));
Task continue = webText.ContinueWith((task) =>  parseData(task.Result));
webText.Start();
continue.Wait();

বিশেষ পরিস্থিতিতে কি একজনের চেয়ে অন্যের চেয়ে বেশি পছন্দ হয়?


3
আপনি মুছে যদি Waitদ্বিতীয় উদাহরণে কল তারপর দুটি স্নিপেট (বেশিরভাগই) সমতুল্য হবে।
পরিবেশন করুন


এফওয়াইআই: আপনার getWebPageপদ্ধতি দুটি কোডেই ব্যবহার করা যাবে না। প্রথম কোডে এটির Task<string>রিটার্ন টাইপ থাকে এবং দ্বিতীয়টিতে এটির stringরিটার্ন টাইপ থাকে। সুতরাং মূলত আপনার কোডটি সংকলন করে না। - যদি সুনির্দিষ্ট হয়।
রই নমির

উত্তর:


101

দ্বিতীয় কোডটিতে , আপনি ধারাবাহিকভাবে ধারাবাহিকতাটি সম্পূর্ণ হওয়ার জন্য অপেক্ষা করছেন । প্রথম সংস্করণে, পদ্ধতিটি প্রথম awaitপ্রকাশটি হিট করার সাথে সাথে কলারের কাছে ফিরে আসবে যা ইতিমধ্যে সম্পূর্ণ হয়নি।

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

আমি আপনাকে উভয়ের সাথে ক্রিয়াকলাপের সামান্য বৃহত্তর ক্রমটি প্রয়োগ করার চেষ্টা করার পরামর্শ দিচ্ছি awaitএবং Task.ContinueWith- এটি সত্যই চক্ষুচঞ্চল হতে পারে।


2
দুটি স্নিপেটের মধ্যে পরিচালনা করার ত্রুটিটিও পৃথক; সাধারণভাবে কাজ করা আরো সহজ সাথে awaitবেশি ContinueWithযে বিষয়ে।
পরিবেশন করুন

@ সার্ভে: সত্য, এর আশেপাশে কিছু যুক্ত হবে।
জন স্কিটি

1
পূর্বপরিকল্পনা এছাড়াও পুরোপুরি ভিন্ন, অর্থাত্, কোন প্রসঙ্গে parseDataএ সঞ্চালন করে।
স্টিফেন Cleary

আপনি যখন বলছেন অপেক্ষাটি কল করার প্রসঙ্গে সুস্পষ্টভাবে ধারাবাহিকতার সময়সূচিটি নির্ধারণ করবে , আপনি কি এর সুবিধাটি ব্যাখ্যা করতে পারবেন এবং অন্যান্য পরিস্থিতিতে কী ঘটে?
হ্যারিসন

4
@ হ্যারিসন: আপনি একটি উইনফর্মস অ্যাপটি লিখছেন তা কল্পনা করুন - আপনি যদি একটি অ্যাসিঙ্ক পদ্ধতি লিখেন, ডিফল্টরূপে পদ্ধতির সমস্ত কোড ইউআই থ্রেডে চলবে, কারণ ধারাবাহিকতাটি সেখানে নির্ধারিত হবে। আপনি যদি ধারাবাহিকতাটি কোথায় চালাতে চান তা যদি নির্দিষ্ট না করে থাকেন তবে ডিফল্টটি কী তা আমি জানি না তবে এটি সহজেই থ্রেড পুলের থ্রেডে চালানো শেষ হতে পারে ... আপনি যে ইউআই, ইত্যাদি অ্যাক্সেস করতে পারবেন না ইত্যাদি ইত্যাদি easily ।
জন স্কিটি

100

আমি সম্প্রতি স্নিপেটের কোড সিক্যুয়েন্সটি ব্যবহার করেছি যা আমি সম্প্রতি অ্যাসিঙ্ক সলভ ব্যবহার করে পার্থক্য এবং বিভিন্ন সমস্যার চিত্রিত করতে ব্যবহার করেছি।

মনে করুন আপনার জিইউআই ভিত্তিক অ্যাপ্লিকেশনটিতে এমন কিছু ইভেন্ট হ্যান্ডলার রয়েছে যাতে এতে অনেক সময় লাগে এবং তাই আপনি এটিকে অবিচ্ছিন্ন করতে চাই। আপনি যে সিঙ্ক্রোনাস যুক্তি দিয়ে শুরু করেছেন তা এখানে:

while (true) {
    string result = LoadNextItem().Result;
    if (result.Contains("target")) {
        Counter.Value = result.Length;
        break;
    }
}

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

অ্যাসিনক্রোনাস সংস্করণের প্রথম ধারণা: কেবল ধারাবাহিকতা ব্যবহার করুন! এবং আসুন আপাতত লুপিং অংশটি উপেক্ষা করুন। মানে, কী ভুল হতে পারে?

return LoadNextItem().ContinueWith(t => {
    string result = t.Result;
    if (result.Contains("target")) {
        Counter.Value = result.Length;
    }
});

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

return LoadNextItem().ContinueWith(t => {
    string result = t.Result;
    if (result.Contains("target")) {
        Counter.Value = result.Length;
    }
},
TaskScheduler.FromCurrentSynchronizationContext());

দুর্দান্ত, এখন আমাদের এমন একটি পদ্ধতি রয়েছে যাতে ক্রাশ হয় না! পরিবর্তে এটি নিঃশব্দে ব্যর্থ হয়। ধারাবাহিকতা হ'ল পৃথক কাজগুলি যার সাথে তাদের স্ট্যাটাস পূর্বের কাজটির সাথে আবদ্ধ হয় না। এমনকি লোডনেক্সট আইটেম ত্রুটি থাকলেও, কলকারী কেবলমাত্র একটি কাজ সফলভাবে সম্পন্ন দেখতে পাবে। ঠিক আছে, তারপরে কেবল ব্যতিক্রমটি পাস করুন, যদি একটি থাকে:

return LoadNextItem().ContinueWith(t => {
    if (t.Exception != null) {
        throw t.Exception.InnerException;
    }
    string result = t.Result;
    if (result.Contains("target")) {
        Counter.Value = result.Length;
    }
},
TaskScheduler.FromCurrentSynchronizationContext());

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

Task AsyncLoop() {
    return AsyncLoopTask().ContinueWith(t =>
        Counter.Value = t.Result,
        TaskScheduler.FromCurrentSynchronizationContext());
}
Task<int> AsyncLoopTask() {
    var tcs = new TaskCompletionSource<int>();
    DoIteration(tcs);
    return tcs.Task;
}
void DoIteration(TaskCompletionSource<int> tcs) {
    LoadNextItem().ContinueWith(t => {
        if (t.Exception != null) {
            tcs.TrySetException(t.Exception.InnerException);
        } else if (t.Result.Contains("target")) {
            tcs.TrySetResult(t.Result.Length);
        } else {
            DoIteration(tcs);
        }});
}

অথবা, উপরের সমস্তটির পরিবর্তে, আপনি একই কাজটি করতে async ব্যবহার করতে পারেন:

async Task AsyncLoop() {
    while (true) {
        string result = await LoadNextItem();
        if (result.Contains("target")) {
            Counter.Value = result.Length;
            break;
        }
    }
}

এখন অনেক সুন্দর, তাই না?


ধন্যবাদ, সত্যই চমৎকার ব্যাখ্যা
এলগার মেনসোনাইডস

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