বিভিন্ন ফলাফল সহ একাধিক কার্যের অপেক্ষায়


237

আমার 3 টি কাজ রয়েছে:

private async Task<Cat> FeedCat() {}
private async Task<House> SellHouse() {}
private async Task<Tesla> BuyCar() {}

আমার কোডটি চালিয়ে যাওয়ার আগে তাদের সবার চালানো দরকার এবং আমারও প্রতিটি ফলাফলের প্রয়োজন। ফলাফলগুলির কোনওটিরই একে অপরের সাথে মিল নেই

আমি কীভাবে কল করব এবং 3 টি কার্য শেষ হওয়ার এবং তারপরে ফলাফলগুলি পেতে অপেক্ষা করব?


25
আপনার কি কোনও অর্ডারিং প্রয়োজনীয়তা আছে? অর্থাৎ, আপনি কি বিড়ালকে খাওয়ানো না হওয়া পর্যন্ত বাড়িটি বিক্রি করতে চান না?
এরিক লিপার্ট

উত্তর:


411

আপনি ব্যবহার করার পরে WhenAll, ফলাফলগুলি স্বতন্ত্রভাবে এটিকে টেনে আনতে পারেন await:

var catTask = FeedCat();
var houseTask = SellHouse();
var carTask = BuyCar();

await Task.WhenAll(catTask, houseTask, carTask);

var cat = await catTask;
var house = await houseTask;
var car = await carTask;

আপনি এটিও ব্যবহার করতে পারেন Task.Result(যেহেতু আপনি জানেন যে এগুলি সবগুলি সফলভাবে শেষ হয়েছে)। তবে, আমি এটি ব্যবহার করার পরামর্শ দিচ্ছি awaitকারণ এটি স্পষ্টভাবে সঠিক, Resultঅন্য পরিস্থিতিতে যেমন সমস্যা তৈরি করতে পারে।


83
আপনি WhenAllএটিকে পুরোপুরি সরাতে পারেন ; অপেক্ষারত কাজগুলি সমস্ত শেষ না হওয়া অবধি 3 টি পরবর্তী কার্যভারের আগে আপনি সরে না যাওয়ার বিষয়টি নিশ্চিত করবেন।
পরিবেশন করুন

134
Task.WhenAll()সমান্তরাল মোডে টাস্ক চালানোর অনুমতি দেয় । @ সার্ভি কেন এটি সরানোর পরামর্শ দিয়েছে তা আমি বুঝতে পারি না। WhenAllএগুলি ছাড়া তারা একে একে চালানো হবে
সের্গেই জি।

87
@ সার্জে: কাজগুলি তত্ক্ষণাত্ কার্যকর করা শুরু করে। উদাহরণস্বরূপ, catTaskইতিমধ্যে এটি ফিরে আসার সময় দিয়ে চলছে FeedCat। সুতরাং উভয় পদ্ধতির কাজ করবে - একমাত্র প্রশ্ন হ'ল আপনি কি awaitতাদের একবারে একসাথে চান বা সমস্ত একসাথে চান। ত্রুটি হ্যান্ডলিংটি কিছুটা পৃথক - আপনি যদি ব্যবহার করেন Task.WhenAllতবে তা awaitতাদের সকলেরই হয়ে যাবে, এমনকি যদি তাদের মধ্যে একটিও প্রাথমিকভাবে ব্যর্থ হয়।
স্টিফেন ক্লিয়ারি 12

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

37
@ সের্গে: মূলটি হ'ল অ্যাসিনক্রোনাস পদ্ধতিগুলি সর্বদা "হট" (ইতিমধ্যে শুরু) কার্যগুলি ফিরিয়ে দেয়।
স্টিফেন ক্লিয়ারি

99

awaitএগুলি শুরু করার পরে কেবল তিনটি কাজ আলাদা।

var catTask = FeedCat();
var houseTask = SellHouse();
var carTask = BuyCar();

var cat = await catTask;
var house = await houseTask;
var car = await carTask;

8
@ বরজিট্টা না, এটি মিথ্যা। তারা তাদের কাজ সমান্তরালভাবে করবেন। এটি চালানোর জন্য নির্দ্বিধায় এবং নিজের জন্য দেখুন।

5
লোকেরা বছরের পর বছর পরে একই প্রশ্ন জিজ্ঞাসা করে চলেছে ... আমি আবারও জোর দেওয়া জরুরি যে উত্তরটির শরীরে কোনও কাজ " তৈরি শুরু " : সম্ভবত তারা মন্তব্য পড়তে বিরক্ত করবেন না

9
@ স্টেফেন ইয়র্ক Task.WhenAllকোনও পর্যবেক্ষণযোগ্য উপায়ে প্রোগ্রামের আচরণ সম্পর্কে আক্ষরিক কিছুই পরিবর্তন যুক্ত করা হচ্ছে । এটি একটি নিখুঁতভাবে অনর্থক পদ্ধতি কল। আপনি এটি একটি নান্দনিক পছন্দ হিসাবে পছন্দ করতে চাইলে আপনাকে স্বাগত জানাই, তবে কোড কী করে তা পরিবর্তন করে না। কোড সঞ্চালনের সময় সঙ্গে বা যে পদ্ধতি কল ছাড়া অভিন্ন হতে হবে (অবশ্য টেকনিক্যালি একটা হবেন সত্যিই ছোট কলিং জন্য ওভারহেড WhenAll, কিন্তু এই তুচ্ছ হওয়া উচিত), শুধুমাত্র সংস্করণ উপার্জন সামান্য এই সংস্করণের তুলনায় চালানোর জন্য আর।
Servy

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

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

37

আপনি যদি সি # 7 ব্যবহার করছেন তবে আপনি এই জাতীয় উপায়ে র‍্যাপার পদ্ধতিটি ব্যবহার করতে পারেন ...

public static class TaskEx
{
    public static async Task<(T1, T2)> WhenAll<T1, T2>(Task<T1> task1, Task<T2> task2)
    {
        return (await task1, await task2);
    }
}

... আপনি যখন বিভিন্ন রিটার্নের ধরণের সাথে একাধিক টাস্কের জন্য অপেক্ষা করতে চান তখন এর মতো সুবিধাজনক সিনট্যাক্স সক্ষম করতে। আপনাকে অবশ্যই অপেক্ষা করতে বিভিন্ন সংখ্যক কাজের জন্য একাধিক ওভারলোড করতে হবে।

var (someInt, someString) = await TaskEx.WhenAll(GetIntAsync(), GetStringAsync());

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


টিপলসগুলি এখানে কেবল জড়িত সি # 7 বৈশিষ্ট্য। যারা অবশ্যই চূড়ান্ত রিলিজ হয়।
জোয়েল মুলার

আমি টিপলস এবং সি # about সম্পর্কে জানি I আমার অর্থ আমি যখন পদ্ধতিটি পাই না তখন সবগুলি কীভাবে টিপলস দেয়। কি নামস্থান / প্যাকেজ?
ইয়ুরি শেেরবাকভ

@ ইউরিশ্যাচারবাকভ Task.WhenAll()একটি টুপল ফিরিয়ে দিচ্ছেন না। Resultকাজটি Task.WhenAll()সম্পূর্ণ করার পরে প্রদত্ত টাস্কগুলির বৈশিষ্ট্য থেকে একটি নির্মাণ করা হচ্ছে ।
ক্রিস চরবারুক

2
.Resultআপনার উদাহরণটি অনুলিপি করে অন্য লোকেদের খারাপ অভ্যাস চালিয়ে যাওয়া এড়াতে স্টিফেনের যুক্তি অনুসারে কলগুলি প্রতিস্থাপন করার পরামর্শ দেব ।
জুলাইগলন

আমি ভাবছি কেন এই পদ্ধতিটি কাঠামোর এই অংশ নয়? এটি খুব দরকারী বলে মনে হচ্ছে। এগুলি কি সময়ের বাইরে চলে গিয়েছিল এবং একক রিটার্ন টাইপে থামতে হয়েছিল?
ইয়ান গ্রেঞ্জার

14

তিন কর্ম দেওয়া - FeedCat(), SellHouse()এবং BuyCar(), দুই আকর্ষণীয় মামলা থাকে: পারেন তারা সবাই সম্পূর্ণ সিঙ্ক্রোনাস (কিছু কারণে, সম্ভবত ক্যাশে বা কোন ত্রুটির), অথবা তারা করবেন না।

আসুন আমরা প্রশ্ন থেকে বলি:

Task<string> DoTheThings() {
    Task<Cat> x = FeedCat();
    Task<House> y = SellHouse();
    Task<Tesla> z = BuyCar();
    // what here?
}

এখন, একটি সহজ পদ্ধতি হবে:

Task.WhenAll(x, y, z);

তবে ... ফলাফলগুলি প্রক্রিয়া করার জন্য এটি সুবিধাজনক নয়; আমরা সাধারণত চাইawait :

async Task<string> DoTheThings() {
    Task<Cat> x = FeedCat();
    Task<House> y = SellHouse();
    Task<Tesla> z = BuyCar();

    await Task.WhenAll(x, y, z);
    // presumably we want to do something with the results...
    return DoWhatever(x.Result, y.Result, z.Result);
}

তবে এটি প্রচুর ওভারহেড করে এবং বিভিন্ন অ্যারে (অ্যারে সহ params Task[]) এবং তালিকাগুলি (অভ্যন্তরীণভাবে) বরাদ্দ করে । এটি কাজ করে, তবে এটি দুর্দান্ত আইএমও নয়। অনেকগুলি উপায়ে কোনও অপারেশন ব্যবহার করা সহজasync এবং awaitপ্রতিটি পরিবর্তে:

async Task<string> DoTheThings() {
    Task<Cat> x = FeedCat();
    Task<House> y = SellHouse();
    Task<Tesla> z = BuyCar();

    // do something with the results...
    return DoWhatever(await x, await y, await z);
}

উপরে মন্তব্য কিছু ব্যবহার বিপক্ষে awaitপরিবর্তে Task.WhenAllতোলে কোনো পার্থক্য কিভাবে কর্ম চালানোর (একই সময়ে, ক্রমানুসারে, ইত্যাদি) জন্য। সর্বোচ্চ স্তরে, / এর জন্য ভাল সংকলক সমর্থনের Task.WhenAll পূর্বাভাস দেয় এবং যখন সেই জিনিসগুলির অস্তিত্ব ছিল না তখন তা কার্যকর ছিল । 3 টি বিচক্ষণ কাজের পরিবর্তে আপনার যখন কাজগুলির একটি স্বেচ্ছাসেবী অ্যারে থাকে তখন এটিও কার্যকর।asyncawait

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

Task<string> DoTheThings() {
    Task<Cat> x = FeedCat();
    Task<House> y = SellHouse();
    Task<Tesla> z = BuyCar();

    if(x.Status == TaskStatus.RanToCompletion &&
       y.Status == TaskStatus.RanToCompletion &&
       z.Status == TaskStatus.RanToCompletion)
        return Task.FromResult(
          DoWhatever(a.Result, b.Result, c.Result));
       // we can safely access .Result, as they are known
       // to be ran-to-completion

    return Awaited(x, y, z);
}

async Task Awaited(Task<Cat> a, Task<House> b, Task<Tesla> c) {
    return DoWhatever(await x, await y, await z);
}

এই "অ্যাসিঙ্ক ফ্যালব্যাক সহ সিঙ্ক পাথ" পদ্ধতির ক্রমবর্ধমান বিশেষত উচ্চ পারফরম্যান্স কোড যেখানে সিঙ্ক্রোনাস সম্পূর্ণকরণ তুলনামূলকভাবে ঘন ঘন হয় increasingly মনে রাখবেন যে সমাপ্তি সর্বদা সত্যই অ্যাসিনক্রোনাস থাকে তবে এগুলি কোনও উপকারে আসবে না।

অতিরিক্ত জিনিসগুলি যা এখানে প্রয়োগ হয়:

  1. সাম্প্রতিক সি # এর সাথে, asyncফালব্যাক পদ্ধতিটির জন্য একটি সাধারণ প্যাটার্নটি সাধারণত স্থানীয় ফাংশন হিসাবে প্রয়োগ করা হয়:

    Task<string> DoTheThings() {
        async Task<string> Awaited(Task<Cat> a, Task<House> b, Task<Tesla> c) {
            return DoWhatever(await a, await b, await c);
        }
        Task<Cat> x = FeedCat();
        Task<House> y = SellHouse();
        Task<Tesla> z = BuyCar();
    
        if(x.Status == TaskStatus.RanToCompletion &&
           y.Status == TaskStatus.RanToCompletion &&
           z.Status == TaskStatus.RanToCompletion)
            return Task.FromResult(
              DoWhatever(a.Result, b.Result, c.Result));
           // we can safely access .Result, as they are known
           // to be ran-to-completion
    
        return Awaited(x, y, z);
    }
  2. পছন্দ ValueTask<T>করার Task<T>যদি বিভিন্ন রিটার্ন মান কি কখনো সম্পূর্ণরূপে সিঙ্ক্রোনাস জিনিস ভাল সুযোগ:

    ValueTask<string> DoTheThings() {
        async ValueTask<string> Awaited(ValueTask<Cat> a, Task<House> b, Task<Tesla> c) {
            return DoWhatever(await a, await b, await c);
        }
        ValueTask<Cat> x = FeedCat();
        ValueTask<House> y = SellHouse();
        ValueTask<Tesla> z = BuyCar();
    
        if(x.IsCompletedSuccessfully &&
           y.IsCompletedSuccessfully &&
           z.IsCompletedSuccessfully)
            return new ValueTask<string>(
              DoWhatever(a.Result, b.Result, c.Result));
           // we can safely access .Result, as they are known
           // to be ran-to-completion
    
        return Awaited(x, y, z);
    }
  3. যদি সম্ভব হয় তবে অগ্রাধিকার IsCompletedSuccessfullyদিন Status == TaskStatus.RanToCompletion; এটি এখন নেট নেট Taskএবং এর জন্য সর্বত্র রয়েছে everywhereValueTask<T>


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

@ সার্ভে আপনি ঠিক বলেছেন, এটি ছিল মন্তব্যসমূহ; আমি ফলাফল ব্যবহার দেখানোর জন্য একটি খামচি যুক্ত করতে হবে
মার্ক Gravell

@Servy খামচি যোগ
মার্ক Gravell

এছাড়াও আপনি যদি সিঙ্ক্রোনাস টাস্কগুলি হস্তান্তর করার তাড়াতাড়ি গ্রহণ করতে চলেছেন তবে আপনি সফলভাবে সম্পন্ন হওয়াগুলির চেয়ে আপনি যেকোনও কাজ সুসংগতভাবে বাতিল বা ত্রুটিযুক্তভাবে পরিচালনা করতে পারেন। যদি আপনি সিদ্ধান্ত নিয়ে থাকেন যে এটি একটি অপ্টিমাইজেশন যা আপনার প্রোগ্রামটির প্রয়োজন (যা বিরল হবে, তবে ঘটবে) তবে আপনিও পুরোপুরি যেতে পারেন।
6:38

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

12

আপনি এগুলি কার্যগুলিতে সঞ্চয় করতে পারেন, তারপরে তাদের সকলের জন্য অপেক্ষা করুন:

var catTask = FeedCat();
var houseTask = SellHouse();
var carTask = BuyCar();

await Task.WhenAll(catTask, houseTask, carTask);

Cat cat = await catTask;
House house = await houseTask;
Car car = await carTask;

পদ্ধতিটি ইতিমধ্যে কার্যকর করা হয়েছে বলে var catTask = FeedCat()ক্রিয়াকলাপটি কার্যকর করে FeedCat()এবং অংশটিকে অপ্রয়োজনীয় catTaskতৈরিতে ফলাফল সংরক্ষণ করে না await Task.WhenAll()??
ক্রাং প্রাইম

1
@ সানুয়েল যদি তারা ফিরে আসে <t>, তবে না ... তারা অ্যাসিঙ্কটি খোলা শুরু করে, তবে এর জন্য অপেক্ষা করবেন না
রিড কোপসি

আমি এটিকে সঠিক বলে মনে করি না, দয়া করে @ স্টিফেনক্রিয়ারির উত্তরের অধীনে আলোচনাগুলি দেখুন ... এছাড়াও সার্ভির উত্তর দেখুন।
রোসদী কাসিম

1
আমার যদি যোগ করার প্রয়োজন হয়। কনফিগার্টুএইউইট (মিথ্যা)। আমি কি এটি কেবল টাস্কের সাথে যুক্ত করব? যখন সমস্ত বা পরবর্তী প্রতিটি ওয়েটারের সাথে?
অ্যাস্ট্রোশার্প

@ অস্ট্রোশার্প সাধারণভাবে, এটি সবার মধ্যে যুক্ত করা ভাল ধারণা (প্রথমটি সম্পন্ন হলে এটি কার্যকরভাবে উপেক্ষা করা হবে), তবে এই ক্ষেত্রে সম্ভবত প্রথমটি করা ঠিক হবে - যদি না আরও অ্যাসিঙ্ক থাকে স্টাফ পরে ঘটছে।
রিড কোপসি

6

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

var catTask = FeedCat();
var houseTask = SellHouse();
var carTask = BuyCar();

await Task.WhenAll(catTask, houseTask, carTask);

var cat = await catTask;
var house = await houseTask;
var car = await carTask;

নিম্নলিখিত কোডটিতে ফিডকিট ব্যতিক্রম ছুঁড়ে কল্পনা করুন:

var catTask = FeedCat();
var houseTask = SellHouse();
var carTask = BuyCar();

var cat = await catTask;
var house = await houseTask;
var car = await carTask;

সেক্ষেত্রে আপনি কখনও বাড়ির টাস্ক বা কার টাস্কে অপেক্ষা করবেন না। এখানে 3 টি সম্ভাব্য পরিস্থিতি রয়েছে:

  1. ফিডকাট ব্যর্থ হলে সেলহাউস ইতিমধ্যে সফলভাবে সম্পন্ন হয়েছে। এই ক্ষেত্রে আপনি ভাল আছেন।

  2. সেলহাউস সম্পূর্ণ নয় এবং কিছু সময় ব্যতিক্রম ব্যর্থ হয়। ব্যতিক্রম পর্যবেক্ষণ করা হয় না এবং চূড়ান্তকরণকারী থ্রেডে পুনরায় উত্থিত হবে।

  3. সেলহাউস সম্পূর্ণ নয় এবং এর অভ্যন্তরে অপেক্ষা রয়েছে। আপনার কোডটি এএসপি.নেট সেলহাউসে চলার সাথে সাথে এর কিছু অপেক্ষার কাজটি শেষ হওয়ার সাথে সাথে ব্যর্থ হয়ে যাবে। এটি ঘটেছিল কারণ আপনি মূলত আগুন জ্বালিয়েছেন এবং কল কলটি ভুলে যান এবং ফিডকিট ব্যর্থ হওয়ার সাথে সাথে সিঙ্ক্রোনাইজেশন প্রসঙ্গটি হারিয়ে যায়।

এখানে ত্রুটি রয়েছে যা আপনি কেস (3) এর জন্য পাবেন:

System.AggregateException: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at System.Web.ThreadContext.AssociateWithCurrentThread(Boolean setImpersonationContext)
   at System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationContext)
   at System.Web.HttpApplication.System.Web.Util.ISyncContext.Enter()
   at System.Web.Util.SynchronizationHelper.SafeWrapCallback(Action action)
   at System.Threading.Tasks.Task.Execute()
   --- End of inner exception stack trace ---
---> (Inner Exception #0) System.NullReferenceException: Object reference not set to an instance of an object.
   at System.Web.ThreadContext.AssociateWithCurrentThread(Boolean setImpersonationContext)
   at System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationContext)
   at System.Web.HttpApplication.System.Web.Util.ISyncContext.Enter()
   at System.Web.Util.SynchronizationHelper.SafeWrapCallback(Action action)
   at System.Threading.Tasks.Task.Execute()<---

কেসের জন্য (২) আপনি একই ত্রুটি পাবেন তবে মূল ব্যতিক্রম স্ট্যাক ট্রেস সহ।

.NET 4.0 এর জন্য এবং পরবর্তীকালে আপনি টাস্কশেডুলারউনোভস্ক্রিড টাস্কএক্সসেপশন ব্যবহার করে অনাবৃত আপত্তিগুলি ধরতে পারেন। .NET 4.5 এর জন্য এবং পরে অবরুদ্ধ সংরক্ষিত ব্যতিক্রমগুলি .NET 4.0 এর জন্য ডিফল্টরূপে গিলে ফেলা অবরুদ্ধ করা ব্যতিক্রম আপনার প্রক্রিয়াটি ক্র্যাশ হয়ে যাবে।

আরও বিশদ এখানে: টাস ব্যাতিকাল


2

আপনি Task.WhenAllউল্লিখিত হিসাবে ব্যবহার করতে পারেন , বা Task.WaitAllআপনি থ্রেডটি অপেক্ষা করতে চান কিনা তার উপর নির্ভর করে। উভয়ের ব্যাখ্যার জন্য লিঙ্কটি একবার দেখুন।

ওয়েটআল বনাম যখন সমস্ত


2

ব্যবহার করুন Task.WhenAllএবং তারপরে ফলাফলগুলির জন্য অপেক্ষা করুন:

var tCat = FeedCat();
var tHouse = SellHouse();
var tCar = BuyCar();
await Task.WhenAll(tCat, tHouse, tCar);
Cat cat = await tCat;
House house = await tHouse;
Tesla car = await tCar; 
//as they have all definitely finished, you could also use Task.Value.

মিমি ... টাস্ক.ভ্যালু নয় (সম্ভবত এটি 2013 সালে বিদ্যমান ছিল?), বরং টিটিগি.আরসাল্ট, টি হাউস.সিসাল্ট বা টিসিআর.সাল্ট
স্টিফেন ইয়র্ক

1

ফরওয়ার্ড সতর্কতা

এই এবং অন্যান্য অনুরূপ থ্রেডগুলিতে যারা আসছেন তাদের কেবলমাত্র দ্রুত অগ্রগতি হিসাবে অ্যাসিঙ্ক + ওয়েভেট + টাস্ক টুল-সেট ব্যবহার করে সত্তা ফ্রেমওয়ার্ককে সমান্তরাল করার উপায় খুঁজছেন : এখানে প্রদর্শিত প্যাটার্নটি দুর্দান্ত, তবে এটি যখন ইএফ-এর বিশেষ স্নোফ্লেকের কথা আসে তখন আপনি তা পাবেন না সমান্তরাল সম্পাদন অর্জন করুন যতক্ষণ না আপনি প্রতিটি এবং অ্যাসিঙ্ক () কল জড়িত প্রত্যেকটির অভ্যন্তরে পৃথক (নতুন) ডিবি-প্রসঙ্গ-উদাহরণ ব্যবহার করেন না।

ইএফ-ডিবি-কনটেক্সটগুলির অন্তর্নিহিত নকশার সীমাবদ্ধতার কারণে এই ধরণের জিনিসটি প্রয়োজনীয় যা একই ইএফ-ডিবি-প্রসঙ্গের দৃষ্টান্তে সমান্তরালে একাধিক প্রশ্ন চালানো নিষেধ করে।


ইতিমধ্যে প্রদত্ত উত্তরের মূলধনটি নির্ধারণ করে, এক বা একাধিক কার্যের ব্যতিক্রমের ফলস্বরূপ আপনি যে সমস্ত মান সংগ্রহ করেছেন তা নিশ্চিত করার উপায় এটি:

  public async Task<string> Foobar() {
    async Task<string> Awaited(Task<Cat> a, Task<House> b, Task<Tesla> c) {
        return DoSomething(await a, await b, await c);
    }

    using (var carTask = BuyCarAsync())
    using (var catTask = FeedCatAsync())
    using (var houseTask = SellHouseAsync())
    {
        if (carTask.Status == TaskStatus.RanToCompletion //triple
            && catTask.Status == TaskStatus.RanToCompletion //cache
            && houseTask.Status == TaskStatus.RanToCompletion) { //hits
            return Task.FromResult(DoSomething(catTask.Result, carTask.Result, houseTask.Result)); //fast-track
        }

        cat = await catTask;
        car = await carTask;
        house = await houseTask;
        //or Task.AwaitAll(carTask, catTask, houseTask);
        //or await Task.WhenAll(carTask, catTask, houseTask);
        //it depends on how you like exception handling better

        return Awaited(catTask, carTask, houseTask);
   }
 }

কম-বেশি একই পারফরম্যান্স বৈশিষ্ট্যযুক্ত একটি বিকল্প বাস্তবায়ন হতে পারে:

 public async Task<string> Foobar() {
    using (var carTask = BuyCarAsync())
    using (var catTask = FeedCatAsync())
    using (var houseTask = SellHouseAsync())
    {
        cat = catTask.Status == TaskStatus.RanToCompletion ? catTask.Result : (await catTask);
        car = carTask.Status == TaskStatus.RanToCompletion ? carTask.Result : (await carTask);
        house = houseTask.Status == TaskStatus.RanToCompletion ? houseTask.Result : (await houseTask);

        return DoSomething(cat, car, house);
     }
 }

-1
var dn = await Task.WhenAll<dynamic>(FeedCat(),SellHouse(),BuyCar());

আপনি যদি ক্যাটটি অ্যাক্সেস করতে চান তবে আপনি এটি করুন:

var ct = (Cat)dn[0];

এটি করা খুব সহজ এবং ব্যবহারে খুব দরকারী, একটি জটিল সমাধানের পরে যাওয়ার দরকার নেই।


1
এটির সাথে একটি মাত্র সমস্যা আছে: dynamicহ'ল শয়তান। এটি কৌশলগত সিওএম ইন্টারপ এবং এ জাতীয় জন্য এবং এটি কোনওরকম পরিস্থিতিতে ব্যবহার করা উচিত নয় যেখানে একেবারেই প্রয়োজন হয় না। বিশেষত যদি আপনি পারফরম্যান্স সম্পর্কে যত্নশীল হন। বা সুরক্ষা টাইপ করুন। বা রিফ্যাক্টরিং। বা ডিবাগিং।
জোয়েল মুয়েলার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.