টাস্কের জন্য কেন অপেক্ষা করা হচ্ছে না? যখন সমস্ত একটি সমষ্টিগত ধারণাটি ফেলে দেয়?


105

এই কোডে:

private async void button1_Click(object sender, EventArgs e) {
    try {
        await Task.WhenAll(DoLongThingAsyncEx1(), DoLongThingAsyncEx2());
    }
    catch (Exception ex) {
        // Expect AggregateException, but got InvalidTimeZoneException
    }
}

Task DoLongThingAsyncEx1() {
    return Task.Run(() => { throw new InvalidTimeZoneException(); });
}

Task DoLongThingAsyncEx2() {
    return Task.Run(() => { throw new InvalidOperation();});
}

আমি WhenAllএকটি তৈরি এবং নিক্ষেপ করার প্রত্যাশা করছিলাম AggregateException, যেহেতু এটির যে অপেক্ষায় ছিল তার অন্তত একটি ব্যতিক্রম ছুঁড়েছিল। পরিবর্তে, আমি এক একটি কাজ ব্যতীত ব্যতিক্রম ফিরে পাচ্ছি।

না WhenAllসবসময় একটি তৈরি করবেন AggregateException?


8
WhenAll নেই একটি তৈরি AggregateException। আপনি যদি আপনার উদাহরণের Task.Waitপরিবর্তে ব্যবহার করেন তবে আপনি awaitধরতে পারবেনAggregateException
পিটার রিচি

4
+1, আমি এটি খুঁজে বের করার চেষ্টা করছি, আমার ডিবাগিং এবং গুগল-ইনগের কয়েক ঘন্টা সঞ্চয় করুন।
কেনেনিজেক্স

বেশ কয়েক বছরে প্রথমবারের জন্য আমার থেকে সমস্ত ব্যাতিক্রমের প্রয়োজন হয়েছিল Task.WhenAllএবং আমি একই ফাঁদে পড়েছি। তাই আমি এই আচরণ সম্পর্কে গভীর বিশদে যাওয়ার চেষ্টা করেছি ।
নাসেরটিও

উত্তর:


78

আমি ঠিক কোথায় জানি না, তবে আমি কোথাও পড়েছি যে নতুন অ্যাসিঙ্ক / কীওয়ার্ডের জন্য অপেক্ষা করে , তারা AggregateExceptionআসল ব্যতিক্রমের মধ্যে মোড়ক খায় ।

সুতরাং, ক্যাচ ব্লকে, আপনি প্রকৃত ব্যতিক্রম পেয়েছেন এবং একত্রিত নয়। এটি আমাদের আরও প্রাকৃতিক এবং স্বজ্ঞাত কোড লিখতে সহায়তা করে।

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

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

বুঝেছি:

বিল ওয়াগনার রচিত একটি অ্যাসিঙ্ক প্রিমিয়ার

বিল ওয়াগনার বলেছেন: ( ব্যতিক্রম ঘটলে )

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


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

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

4
আমি সে সম্পর্কেও ভেবেছিলাম, তবে দুটি সমস্যা এসেছিল: ১) আমি কীভাবে টাস্কটি সংরক্ষণ করব তা বুঝতে পারি না যাতে আমি এটি পরীক্ষা করতে পারি (যেমন "টাস্ক মাই টাস্ক = টাস্কের জন্য অপেক্ষা করুন। যখন সমস্ত (...)" না) এবং 2) আমি অনুমান করি যে আমি অপেক্ষা করি না কখনই কেবল এক ব্যতিক্রম হিসাবে একাধিক ব্যতিক্রম উপস্থাপন করতে পারে তা দেখি না ... কোন ব্যতিক্রমের প্রতিবেদন করা উচিত? এলোমেলোভাবে একটি চয়ন?
মাইকেল রায় লাভট

4
হ্যাঁ, আমি যখন টাস্কটি সঞ্চয় করি এবং প্রতীক্ষার চেষ্টা / ক্যাপচারে এটি পরীক্ষা করি তখন আমি দেখতে পাচ্ছি এটি ব্যতিক্রম সমষ্টিগত এক্সসেপশন। সুতরাং আমি যে ডকগুলি পড়েছি তা সঠিক; Task.WenAll একটি সমষ্টিগত এক্সসেপশন ব্যতিক্রমগুলি গুছিয়ে নিচ্ছে। তবে তারপরে অপেক্ষা করুন সেগুলি মুছে ফেলা হচ্ছে। আমি এখন আপনার নিবন্ধটি পড়ছি, তবে আমি এখনও দেখছি না কীভাবে অপেক্ষাগুলি সমষ্টিগত অনুভূতিগুলি থেকে একক ব্যতিক্রম বেছে নিতে পারে এবং সেই বনামকে আরেকটি ছুঁড়ে ফেলতে পারে ..
মাইকেল রায় লাভট

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

60

আমি জানি এই একটি প্রশ্ন থেকেই উত্তর কিন্তু মনোনীত উত্তর না সত্যিই , অপ এর সমস্যা সমাধান তাই আমি ভাবলাম এই পোস্ট করতে হবে।

এই সমাধানটি আপনাকে সামগ্রিক ব্যতিক্রম দেয় (অর্থাত্ যে সমস্ত ব্যতিক্রমগুলি বিভিন্ন কার্য দ্বারা ছুঁড়ে দেওয়া হয়েছিল) এবং অবরুদ্ধ করে না (কার্যপ্রবাহটি এখনও অবিচ্ছিন্ন)।

async Task Main()
{
    var task = Task.WhenAll(A(), B());

    try
    {
        var results = await task;
        Console.WriteLine(results);
    }
    catch (Exception)
    {
        if (task.Exception != null)
        {
            throw task.Exception;
        }
    }
}

public async Task<int> A()
{
    await Task.Delay(100);
    throw new Exception("A");
}

public async Task<int> B()
{
    await Task.Delay(100);
    throw new Exception("B");
}

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

আশা করি এটি এখনও কার্যকর। আমি জানি আজ আমার এই সমস্যা ছিল


দুর্দান্ত পরিষ্কার উত্তর, এটি আইএমওর নির্বাচিত হওয়া উচিত।
বাইটেডে

4
+1, তবে আপনি কেবল throw task.Exception;এই catchব্লকের ভিতরে রাখতে পারবেন না ? (ব্যতিক্রমগুলি যখন পরিচালনা করা হয় তখন এটি খালি ধরা দেখতে আমাকে বিভ্রান্ত করে))
আনোরজাকেন

নিবন্ধন করুন আমি কেন এটি প্রাথমিকভাবে লিখলাম তা মনে নেই তবে আমি কোনও খারাপ দিক দেখতে পাচ্ছি না তাই আমি এটিকে ক্যাচ ব্লকে স্থানান্তরিত করেছি। ধন্যবাদ
রিচিবান

এই পদ্ধতির একটি ক্ষুদ্রতম দিক হ'ল বাতিল স্থিতি ( Task.IsCanceled) সঠিকভাবে প্রচারিত হয় না। এই মত একটি এক্সটেনশন সাহায্যকারী ব্যবহার সমাধান হতে পারে এই
নসক্রিও

35

একাধিক ব্যতিক্রম ছুঁড়ে ফেলেছে কিনা তা দেখতে আপনি সমস্ত কার্য অতিক্রম করতে পারেন:

private async Task Example()
{
    var tasks = new [] { DoLongThingAsyncEx1(), DoLongThingAsyncEx2() };

    try 
    {
        await Task.WhenAll(tasks);
    }
    catch (Exception ex) 
    {
        var exceptions = tasks.Where(t => t.Exception != null)
                              .Select(t => t.Exception);
    }
}

private Task DoLongThingAsyncEx1()
{
    return Task.Run(() => { throw new InvalidTimeZoneException(); });
}

private Task DoLongThingAsyncEx2()
{
    return Task.Run(() => { throw new InvalidOperationException(); });
}

4
এটা কাজ করে না. WhenAllপ্রথম ব্যতিক্রম থেকে প্রস্থান করে এবং এটি ফেরত দেয়। দেখুন: stackoverflow.com/questions/6123406/waitall-vs-whenall
জেনসন বাটন ঘটনা

15
আগের দুটি মন্তব্য ভুল। কোডটি আসলে কাজ করে এবং exceptionsএতে উভয়ই বাদ দেওয়া ব্যতিক্রম থাকে।
টোবিয়াস

ডওলংথিংএসিএনএক্সএক্স 2 () অবশ্যই নতুন অবৈধ অপারেশন () এর পরিবর্তে নতুন অবৈধ অপসারণ () ছুঁড়ে ফেলতে হবে
কৃত্রিম

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

13

ভেবেছি আমি @ রিচিবারের উত্তরে এটি প্রসারিত করব যে আপনি এই কাজটি থেকে রেফারেন্স করে ক্যাচ ব্লকে অগ্রিগ্রেট এক্সেপশনও পরিচালনা করতে পারবেন। যেমন:

async Task Main()
{
    var task = Task.WhenAll(A(), B());

    try
    {
        var results = await task;
        Console.WriteLine(results);
    }
    catch (Exception ex)
    {
        // This doesn't fire until both tasks
        // are complete. I.e. so after 10 seconds
        // as per the second delay

        // The ex in this instance is the first
        // exception thrown, i.e. "A".
        var firstExceptionThrown = ex;

        // This aggregate contains both "A" and "B".
        var aggregateException = task.Exception;
    }
}

public async Task<int> A()
{
    await Task.Delay(100);
    throw new Exception("A");
}

public async Task<int> B()
{
    // Extra delay to make it clear that the await
    // waits for all tasks to complete, including
    // waiting for this exception.
    await Task.Delay(10000);
    throw new Exception("B");
}

11

আপনি ভাবছেন Task.WaitAll- এটি একটি ছুড়ে ফেলে AggregateException

যখন সমস্ত মুখোমুখি ব্যতিক্রমগুলির তালিকার প্রথম ব্যতিক্রম ছুঁড়ে ফেলেছে।


4
এটি ভুল, WhenAllপদ্ধতি থেকে ফিরে আসা কার্যটির এমন একটি Exceptionসম্পত্তি রয়েছে যা এতে AggregateExceptionফেলে দেওয়া সমস্ত ব্যতিক্রম সমন্বিত InnerExceptions। এখানে যা ঘটছে তা হ'ল নিজের awaitপরিবর্তে প্রথম অভ্যন্তরীণ ব্যতিক্রম ছোঁড়া AggregateException(ডিক্লকোন যেমন বলেছেন)। টাস্কের Waitপদ্ধতির অপেক্ষার পরিবর্তে কল করার ফলে আসল ব্যতিক্রম ছোঁড়ার কারণ হয়।
akafak Gür

6

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

সমস্যাটি

অপেক্ষা taskদ্বারা ফিরে Task.WhenAllশুধুমাত্র প্রথম ব্যতিক্রম ছোঁড়ার AggregateExceptionসঞ্চিত task.Exception, এমনকি যখন একাধিক কর্ম faulted হয়েছে।

জন্য বর্তমান ডক্সTask.WhenAll বলে:

সরবরাহকৃত কোনও কাজ যদি একটি ত্রুটিযুক্ত অবস্থায় সম্পূর্ণ হয় তবে প্রত্যাবর্তিত টাস্কটিও একটি ত্রুটিযুক্ত অবস্থায় সম্পূর্ণ হবে, যেখানে এর ব্যতিক্রমগুলিতে সরবরাহিত প্রতিটি কার্য থেকে আন-র্যাপযুক্ত ব্যতিক্রমগুলির সংশ্লেষণ থাকবে।

যা সঠিক, তবে কখন প্রত্যাবর্তিত কাজটির অপেক্ষায় রয়েছে তার উপরের উল্লিখিত "আনারপ্যাটিং" আচরণ সম্পর্কে কিছুই বলে না।

আমি মনে করি, দস্তাবেজগুলি এটি উল্লেখ করে না কারণ আচরণটি সুনির্দিষ্ট নয়Task.WhenAll

এটা যে কেবল হয় Task.Exceptionধরনের হয় AggregateExceptionএবং জন্য awaitcontinuations এটা সবসময় তার প্রথম ভেতরের ব্যতিক্রম হিসাবে unwrapped পরার নকশা। এটি বেশিরভাগ ক্ষেত্রেই দুর্দান্ত, কারণ সাধারণত Task.Exceptionকেবলমাত্র একটি অভ্যন্তরীণ ব্যতিক্রম থাকে। তবে এই কোডটি বিবেচনা করুন:

Task WhenAllWrong()
{
    var tcs = new TaskCompletionSource<DBNull>();
    tcs.TrySetException(new Exception[]
    {
        new InvalidOperationException(),
        new DivideByZeroException()
    });
    return tcs.Task;
}

var task = WhenAllWrong();    
try
{
    await task;
}
catch (Exception exception)
{
    // task.Exception is an AggregateException with 2 inner exception 
    Assert.IsTrue(task.Exception.InnerExceptions.Count == 2);
    Assert.IsInstanceOfType(task.Exception.InnerExceptions[0], typeof(InvalidOperationException));
    Assert.IsInstanceOfType(task.Exception.InnerExceptions[1], typeof(DivideByZeroException));

    // However, the exception that we caught here is 
    // the first exception from the above InnerExceptions list:
    Assert.IsInstanceOfType(exception, typeof(InvalidOperationException));
    Assert.AreSame(exception, task.Exception.InnerExceptions[0]);
}

এখানে, উদাহরণটি একেবারে ঠিক একইভাবে AggregateExceptionতার প্রথম অভ্যন্তরীণ ব্যতিক্রমকে আবদ্ধ করা যায় InvalidOperationExceptionযা আমরা এটির সাথে থাকতে পারি Task.WhenAll। আমরা সরাসরি DivideByZeroExceptionযেতে না পারলে আমরা পর্যবেক্ষণ করতে ব্যর্থ হতে পারতাম task.Exception.InnerExceptions

মাইক্রোসফ্টের স্টিফেন টাব সম্পর্কিত গিটহাব ইস্যুতে এই আচরণের পেছনের কারণ ব্যাখ্যা করেছেন :

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

অন্য একটি গুরুত্বপূর্ণ বিষয় লক্ষণীয়, এই অনাবৃত আচরণ অগভীর। AggregateException.InnerExceptionsউদাহরণস্বরূপ , এটি কেবল প্রথম ব্যতিক্রমটি কেবল আনআরপট করে এটিকে সেখানে রেখে দেবে, এমনকি এটি অন্যের উদাহরণ হতে পারে AggregateException। এটি বিভ্রান্তির আরও একটি স্তর যুক্ত করতে পারে। উদাহরণস্বরূপ, আসুন এর WhenAllWrongমতো পরিবর্তন করুন :

async Task WhenAllWrong()
{
    await Task.FromException(new AggregateException(
        new InvalidOperationException(),
        new DivideByZeroException()));
}

var task = WhenAllWrong();

try
{
    await task;
}
catch (Exception exception)
{
    // now, task.Exception is an AggregateException with 1 inner exception, 
    // which is itself an instance of AggregateException
    Assert.IsTrue(task.Exception.InnerExceptions.Count == 1);
    Assert.IsInstanceOfType(task.Exception.InnerExceptions[0], typeof(AggregateException));

    // And now the exception that we caught here is that inner AggregateException, 
    // which is also the same object we have thrown from WhenAllWrong:
    var aggregate = exception as AggregateException;
    Assert.IsNotNull(aggregate);
    Assert.AreSame(exception, task.Exception.InnerExceptions[0]);
    Assert.IsInstanceOfType(aggregate.InnerExceptions[0], typeof(InvalidOperationException));
    Assert.IsInstanceOfType(aggregate.InnerExceptions[1], typeof(DivideByZeroException));
}

একটি সমাধান (টিএলডিআর)

সুতরাং, ফিরে await Task.WhenAll(...), আমি ব্যক্তিগতভাবে যা চেয়েছিলাম তা হ'ল সক্ষম হ'ল:

  • যদি কেবল একজনকে ফেলে দেওয়া হয় তবে একটি একক ব্যতিক্রম পান;
  • AggregateExceptionএক বা একাধিক কার্য সম্মিলিতভাবে একাধিক ব্যতিক্রম ছুঁড়ে দেওয়া থাকলে একটি পান ;
  • এটি Taskযাচাই করার জন্য কেবল সংরক্ষণ করতে এড়িয়ে চলুন Task.Exception;
  • বাতিলের অবস্থা সঠিকভাবে (সঞ্চারিত Task.IsCanceled), ভালো কিছু যে না করবে হিসাবে: Task t = Task.WhenAll(...); try { await t; } catch { throw t.Exception; }

আমি এর জন্য নিম্নলিখিত এক্সটেনশন একসাথে রেখেছি:

public static class TaskExt 
{
    /// <summary>
    /// A workaround for getting all of AggregateException.InnerExceptions with try/await/catch
    /// </summary>
    public static Task WithAggregatedExceptions(this Task @this)
    {
        // using AggregateException.Flatten as a bonus
        return @this.ContinueWith(
            continuationFunction: anteTask =>
                anteTask.IsFaulted &&
                anteTask.Exception is AggregateException ex &&
                (ex.InnerExceptions.Count > 1 || ex.InnerException is AggregateException) ?
                Task.FromException(ex.Flatten()) : anteTask,
            cancellationToken: CancellationToken.None,
            TaskContinuationOptions.ExecuteSynchronously,
            scheduler: TaskScheduler.Default).Unwrap();
    }    
}

এখন, নীচেরগুলি আমার এটির মতো কাজ করে:

try
{
    await Task.WhenAll(
        Task.FromException(new InvalidOperationException()),
        Task.FromException(new DivideByZeroException()))
        .WithAggregatedExceptions();
}
catch (OperationCanceledException) 
{
    Trace.WriteLine("Canceled");
}
catch (AggregateException exception)
{
    Trace.WriteLine("2 or more exceptions");
    // Now the exception that we caught here is an AggregateException, 
    // with two inner exceptions:
    var aggregate = exception as AggregateException;
    Assert.IsNotNull(aggregate);
    Assert.IsInstanceOfType(aggregate.InnerExceptions[0], typeof(InvalidOperationException));
    Assert.IsInstanceOfType(aggregate.InnerExceptions[1], typeof(DivideByZeroException));
}
catch (Exception exception)
{
    Trace.WriteLine($"Just a single exception: ${exception.Message}");
}

4
চমত্কার উত্তর
রোলস

-3

এটি আমার পক্ষে কাজ করে

private async Task WhenAllWithExceptions(params Task[] tasks)
{
    var result = await Task.WhenAll(tasks);
    if (result.IsFaulted)
    {
                throw result.Exception;
    }
}

4
WhenAllযেমন হয় না WhenAnyawait Task.WhenAny(tasks)যে কোনও কাজ শেষ হওয়ার সাথে সাথে শেষ হবে। সুতরাং আপনার যদি এমন একটি কাজ থাকে যা অবিলম্বে সম্পূর্ণ হয় এবং সফল হয় এবং অন্য কোনও ব্যতিক্রম ছুঁড়ে দেওয়ার কয়েক সেকেন্ড সময় নেয় তবে এটি কোনও ত্রুটি ছাড়াই অবিলম্বে ফিরে আসবে।
স্ট্রিপলিং ওয়ারিয়র

তারপর নিক্ষেপ লাইন এখানে আঘাত না করা হবে - WhenAll ব্যতিক্রম নিক্ষিপ্ত হবে
thab

-5

আপনার কোডে, http://blogs.msdn.com/b/pfxteam/archive/2011/09/28/task-exception-handling-in-net-4-5- তে বর্ণিত হিসাবে নকশার মাধ্যমে প্রথম ব্যতিক্রমটি ফিরে আসবে । এসপেক্স

আপনার প্রশ্নের হিসাবে, আপনি যদি এইরকম কোড লিখেন তবে আপনি AggreateException পাবেন:

try {
    var result = Task.WhenAll(DoLongThingAsyncEx1(), DoLongThingAsyncEx2()).Result; 
}
catch (Exception ex) {
    // Expect AggregateException here
} 
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.