টাস্ক.সিসল্ট কি .GetAwaiter.GetResult () এর মতো?


328

আমি সম্প্রতি এমন কিছু কোড পড়ছিলাম যা প্রচুর পরিমাণে অ্যাসিঙ্ক পদ্ধতি ব্যবহার করে তবে মাঝে মাঝে সেগুলি সিঙ্ক্রোনালি কার্যকর করতে হবে। কোডটি করে:

Foo foo = GetFooAsync(...).GetAwaiter().GetResult();

এটি কি একই রকম?

Foo foo = GetFooAsync(...).Result;

8
এর ডক্স থেকে GetResult: "এই ধরণের এবং এর সদস্যগণ সংকলক দ্বারা ব্যবহারের উদ্দেশ্যে for" অন্য ব্যক্তির এটি ব্যবহার করা উচিত নয়।
ব্যয়কারী

32
এটিকে "সিঙ্ক ওভার অ্যাসিঙ্ক" বলা হয় এবং আপনি যদি না জানেন যে কীভাবে টাস্কটি বাস্তবায়িত হয় তবে এটি সত্যই খারাপ ধারণা হতে পারে । এটি তাত্ক্ষণিকভাবে অনেক ক্ষেত্রে অচলাবরণ করতে পারে ( উদাহরণস্বরূপ, asyncawait
এমভিসিতে


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

উত্তর:


173

যথেষ্ট. যদিও একটি ছোট পার্থক্য: যদি Taskব্যর্থ হয় তবে GetResult()সরাসরি ঘটে যাওয়া ব্যতিক্রমটি সরাসরি Task.Resultছুঁড়ে ফেলবে , যখন একটি নিক্ষেপ করবে AggregateException। যাইহোক, যখন এটি হয় তখন তাদের উভয়ের ব্যবহার করার কী দরকার async? 100x আরও ভাল বিকল্পটি ব্যবহার করা await

এছাড়াও, আপনি ব্যবহার করতে চাইছেন না GetResult()। এটি কেবল আপনার জন্য নয়, সংকলক ব্যবহারের জন্য বোঝানো হয়েছিল। তবে আপনি যদি বিরক্তিকর না চান তবে AggregateExceptionএটি ব্যবহার করুন।


27
@ জায়েবাউজি নয় যদি আপনার ইউনিট পরীক্ষার কাঠামোটি এসিঙ্ক ইউনিট পরীক্ষাগুলি সমর্থন করে, যা আমার মনে হয় বেশিরভাগ ফ্রেমওয়ার্কগুলির সর্বশেষতম সংস্করণগুলি করে।
সোভিক

15
@ জায়েবাউজি: এমএসটিস্ট, এক্স ইউনিত, এবং নুনিত সমস্ত সমর্থন async Taskইউনিট পরীক্ষা করুন এবং এখন কিছু সময়ের জন্য রয়েছে।
স্টিফেন ক্লিয়ারি

18
100x পিছনে ঠেলাঠেলি - আপনি যদি পুরানো কোডটি মানিয়ে নিচ্ছেন এবং অপেক্ষাটি ব্যবহার করে পুনর্লিখনের প্রয়োজন হয় তবে অপেক্ষা করা 1000x এর চেয়ে খারাপ।
আটকে


15
The 100x better option is to use await.আমি এ জাতীয় বিবৃতি ঘৃণা করি, যদি আমি awaitএর সামনে থাপ্পর মারতে পারতাম। কিন্তু, যখন আমি যা ঘন ঘন আমার হবে মত অ ASYNC কোড বিরুদ্ধে কাজ ASYNC কোড পাওয়ার জন্য চেষ্টা করছি অনেক Xamarin মধ্যে, আমি ভালো জিনিস ব্যবহার করতে থাকার শেষ ContinueWithঅনুক্রমে অনেক এটা UI 'তে অচলাবস্থা না করা। সম্পাদনা: আমি জানি এই পুরোনো, কিন্তু যে আমার হতাশা গবেষনার উত্তরগুলি পরিস্থিতিতে জন্য কোন বিকল্প সঙ্গে রাষ্ট্র এই হল যেখানে আপনি শুধু ব্যবহার করতে পারবেন না উপশম নেই await
থমাস এফ।

147

Task.GetAwaiter().GetResult()এটির উপরে পছন্দ হয় Task.Waitএবং Task.Resultকারণ এটি ব্যতিক্রমগুলিকে একটি মুড়ে ফেলার পরিবর্তে প্রচার করে AggregateException। যাইহোক, তিনটি পদ্ধতিই অচলাবস্থা এবং থ্রেড পুল অনাহার সংক্রান্ত সমস্যার সম্ভাবনা তৈরি করে। তাদের সকলের পক্ষে এড়ানো উচিত async/await

নীচের উক্তিটি ব্যাখ্যা করে যে কেন Task.Waitএবং Task.Resultকেবলমাত্র Task.GetAwaiter().GetResult()"খুব উচ্চমাত্রার সামঞ্জস্যের বারের কারণে" এর ব্যতিক্রম প্রচারের আচরণ থাকে না ।

যেমনটি আমি আগেই উল্লেখ করেছি যে আমাদের একটি খুব উচ্চতর সামঞ্জস্যতা বার রয়েছে এবং সুতরাং আমরা পরিবর্তনগুলি ভঙ্গ করতে এড়ানো করেছি've যেমন, Task.Waitসর্বদা মোড়কের আসল আচরণ ধরে রাখে। তবে আপনি নিজেকে কিছু উন্নত পরিস্থিতিতে খুঁজে পেতে পারেন যেখানে আপনি নিযুক্ত সিঙ্ক্রোনাস ব্লকিংয়ের অনুরূপ আচরণ চান Task.Waitতবে যেখানে আপনি মূল ব্যতিক্রমটিকে কোনও জায়গায় আবদ্ধ করার পরিবর্তে মোড়কানো প্রচার করতে চান AggregateException। এটি অর্জন করতে, আপনি সরাসরি টাস্কের প্রতীক্ষককে লক্ষ্য করতে পারেন। আপনি যখন " await task;" লেখেন , সংকলকটি সেই Task.GetAwaiter()পদ্ধতির ব্যবহারে অনুবাদ করে , যা একটি GetResult()পদ্ধতি রয়েছে এমন উদাহরণ দেয় । কোনও ত্রুটিযুক্ত টাস্কে ব্যবহার করা হলে, GetResult()মূল ব্যতিক্রমটি প্রচার করবে (এভাবেই " await task;" তার আচরণ পায়)। আপনি এইভাবে ব্যবহার করতে পারেন “task.GetAwaiter().GetResult()”আপনি যদি সরাসরি এই প্রচারের যুক্তিটি উপস্থাপন করতে চান।

https://blogs.msdn.microsoft.com/pfxteam/2011/09/28/task-exception-handling-in-net-4-5/

" GetResult" এর অর্থ আসলে "ত্রুটির জন্য কার্য পরীক্ষা করুন"

সাধারণভাবে, আমি একটি অ্যাসিক্রোনাস টাস্কে সুসংগতভাবে ব্লক করা এড়ানোর জন্য যথাসাধ্য চেষ্টা করি। যাইহোক, এমন কয়েকটি মুখ্য পরিস্থিতি রয়েছে যেখানে আমি সেই নির্দেশিকা লঙ্ঘন করি। এই বিরল পরিস্থিতিতে, আমার পছন্দের পদ্ধতিটি GetAwaiter().GetResult()কারণ এটি একটিতে আবৃত না করে টাস্ক ব্যতিক্রমগুলি সংরক্ষণ করে AggregateException

http://blog.stephencleary.com/2014/12/a-tour-of-task-part-6-results.html


3
সুতরাং মূলত Task.GetAwaiter().GetResult()সমান await task। আমি ধরে নিই যে পদ্ধতিটি চিহ্নিত করতে না পারলে প্রথম বিকল্পটি ব্যবহৃত হয় async(উদাহরণস্বরূপ কনস্ট্রাক্টর)। এটা কি ঠিক? যদি হ্যাঁ, তবে এটি শীর্ষ উত্তরটির সাথে সংঘর্ষে এটি এটি নয়টালি
ওলেগি

5
@ ওলিগি: এর Task.GetAwaiter().GetResult()সমতুল্য Task.Waitএবং Task.Result(এর মধ্যে তিনটিই একযোগে ব্লক করবে এবং অচলাবস্থার সম্ভাবনা থাকবে) তবে অপেক্ষার কাজটির Task.GetAwaiter().GetResult()ব্যতিক্রমী প্রচার আচরণ রয়েছে।
নিতিন আগরওয়াল

আপনি এই দৃশ্যে (টাস্ক) দিয়ে অচলাবস্থা এড়াতে পারবেন না on কনফিগুরেএওয়েট (মিথ্যা) etGetAwaiter ()। GetResult (); ?
ড্যানিয়েল লরেঞ্জ

3
@ ড্যানিয়েললরেঞ্জ: নীচের উদ্ধৃতিটি দেখুন: "ডেডলকগুলি এড়াতে কনফিগারআউট (মিথ্যা) ব্যবহার করা একটি বিপজ্জনক অনুশীলন। সমস্ত তৃতীয় সহ ব্লকিং কোড দ্বারা আহ্বৃত সমস্ত পদ্ধতির ট্রানজিটিভ ক্লোজারে প্রতিটি অপেক্ষার জন্য আপনাকে কনফিগারআউট (মিথ্যা) ব্যবহার করতে হবে including - এবং দ্বিতীয় পক্ষের কোড। অচলাবস্থা এড়াতে কনফিগারআউট (মিথ্যা) ব্যবহার করা সর্বোত্তম মাত্র একটি হ্যাক) ... আরও ভাল সমাধান হ'ল "অ্যাসিঙ্ক কোডটি ব্লক করবেন না" "" - blog.stephencleary.com/2012/07/dont- block
নিতিন আগরওয়াল

4
আমি পাই না। Task.Wait এবং Task.Result ডিজাইন দ্বারা ভেঙে গেছে? কেন তারা অপ্রচলিত হয় না?
osexpert

69

https://github.com/aspnet/Security/issues/59

"একটি শেষ মন্তব্য: আপনার ব্যবহার এড়ানো Task.Resultএবং Task.Waitযতটা সম্ভব সম্ভব হওয়া উচিত যতক্ষণ না তারা সর্বদা অভ্যন্তরীণ ব্যতিক্রমটিকে একটি ক্ষেত্রে সজ্জিত করে AggregateExceptionএবং জেনেরিক দ্বারা বার্তাটি প্রতিস্থাপন করে (এক বা একাধিক ত্রুটি ঘটেছে), যা ডিবাগিংকে আরও শক্ত করে তোলে Even এমনকি সিঙ্ক্রোনাস সংস্করণটি না থাকলেও এটি প্রায়শই ব্যবহার করা যাবেনা, Task.GetAwaiter().GetResult()পরিবর্তে ব্যবহারের জন্য আপনার দৃ strongly়তার সাথে বিবেচনা করা উচিত ""


20
উত্সটি এখানে উল্লেখ করা হয়েছে এমন কেউ রেফারেন্স ছাড়াই অন্য কারও উদ্ধৃতি দিচ্ছেন। প্রসঙ্গে বিবেচনা করুন: আমি প্রচুর লোককে অন্ধভাবে গেটএইউটার () ব্যবহার করে দেখতে পাচ্ছি Get
জ্যাক উকলেজা

2
সুতরাং আমাদের এটি ব্যবহার করা উচিত নয়?
তোফুটিম

11
যদি দুটি কার্য একটি ব্যতিক্রমের সাথে শেষ হয় তবে আপনি এই দৃশ্যে দ্বিতীয়টি আলগা করবেন Task.WhenAll(task1, task2).GetAwaiter().GetResult();
মনসাইনর

এখানে আরও একটি উদাহরণ রয়েছে: github.com/aspnet/AspNetCore/issues/13611
জর্জ চাখিদেজে

33

আরেকটি পার্থক্য হ'ল asyncফাংশনটি তার Taskপরিবর্তে ফিরে আসে যখন Task<T>আপনি ব্যবহার করতে পারবেন না

GetFooAsync(...).Result;

যেহেতু

GetFooAsync(...).GetAwaiter().GetResult();

এখনো কাজ করে.

আমি জানি প্রশ্নে উদাহরণ কোডটি মামলার জন্য Task<T>, তবে প্রশ্নটি সাধারণত জিজ্ঞাসা করা হয়।


1
এটি সত্য নয়। আমার ফ্রিডলটি দেখুন
বি

3
@wjciech_rak আপনার কোডটিতে আপনি ব্যবহার Resultকরছেন GetIntAsync()যা কোনটিই ফেরত দেয় Task<int>না Task। আমি আপনাকে আমার উত্তরটি আবার পড়ার পরামর্শ দিচ্ছি।
নুরি তাসদেমির

1
আপনি ঠিক বলেছেন, প্রথমে আমি বুঝতে পেরেছিলাম আপনি উত্তর দিয়েছিলেন যে আপনি কোনও ফাংশনের GetFooAsync(...).Result অভ্যন্তরে ফিরে আসতে পারেন না Task। এটি এখন অর্থবোধ করে, যেহেতু সি # তে কোনও শূন্য বৈশিষ্ট্য নেই ( Task.Resultএকটি সম্পত্তি) তবে আপনি অবশ্যই একটি অকার্যকর পদ্ধতিতে কল করতে পারেন।
wojciech_rak 24'18

22

ইতিমধ্যে উল্লিখিত হিসাবে যদি আপনি ব্যবহার করতে পারেন await। আপনি কোড সিঙ্ক্রোনাস চালানোর মত উল্লেখ প্রয়োজন .GetAwaiter().GetResult(), .Resultবা .Wait()হিসাবে অনেক মন্তব্য / উত্তর বলেন ডেডলক জন্য একটি ঝুঁকি নেই। যেহেতু আমরা বেশিরভাগ অনেলাইনারদের পছন্দ করি আপনি এগুলি ব্যবহার করতে পারেন.Net 4.5<

একটি অ্যাসিঙ্ক পদ্ধতির মাধ্যমে একটি মান অর্জন করা:

var result = Task.Run(() => asyncGetValue()).Result;

সুসংগতভাবে একটি অ্যাসিঙ্ক পদ্ধতিতে কল করা হচ্ছে

Task.Run(() => asyncMethod()).Wait();

কোনও অচলাবস্থার সমস্যা ব্যবহারের কারণে ঘটবে না Task.Run

সূত্র:

https://stackoverflow.com/a/32429753/3850405


1

যদি কোনও টাস্ক ত্রুটিযুক্ত থাকে তবে ধারাবাহিকতা কোডটি ওয়েটারকে কল করলে ব্যতিক্রমটি আবার ছুঁড়ে ফেলা হয় etGETResult ()। গেটআরসাল্টকে কল করার পরিবর্তে আমরা কেবল কার্যের ফলাফল সম্পত্তি অ্যাক্সেস করতে পারি। গেটআরসাল্ট কল করার সুবিধাটি হ'ল যদি কার্যটি ত্রুটি থেকে যায় তবে ব্যতিক্রমটিকে AggregateException এ মোড়ানো না করে সরাসরি ছুঁড়ে দেওয়া হয়, সহজ এবং ক্লিনার ক্যাচ ব্লককে অনুমতি দেয়।

ননজেনেরিক কাজের জন্য, গেটআরসাল্ট () এর একটি শূন্য রিটার্ন মান রয়েছে। এর কার্যকর ফাংশনটি কেবলমাত্র ব্যতিক্রমগুলি পুনর্বিবেচনা করার জন্য।

উত্স: সংক্ষেপে সি # 7.0

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