আমার কি এই উদ্বেগের বিষয়ে "এই অ্যাসিঙ্ক পদ্ধতিতে অপেক্ষারত 'অপারেটরগুলির অভাব রয়েছে এবং এটি সিঙ্ক্রোনালি চালিত হবে" তা নিয়ে আমি কি চিন্তা করব?


93

আমার একটি ইন্টারফেস রয়েছে যা কিছু অ্যাসিঙ্ক পদ্ধতি মেলে। আরও সুনির্দিষ্টভাবে এর মধ্যে এমন পদ্ধতিগুলির সংজ্ঞা দেওয়া আছে যা টাস্ক বা টাস্ক <T> এ ফিরে আসে। আমি async / অপেক্ষার কীওয়ার্ড ব্যবহার করছি।

আমি এই ইন্টারফেস বাস্তবায়নের প্রক্রিয়াধীন। যাইহোক, এই কয়েকটি পদ্ধতির মধ্যে এই প্রয়োগের অপেক্ষা করার মতো কিছুই নেই। যে কারণে আমি সংকলক সতর্কতা পাচ্ছি "" এই অ্যাসিঙ্ক পদ্ধতির 'অপেক্ষারত' অপারেটরগুলির অভাব রয়েছে এবং সিঙ্ক্রোনিকভাবে চলবে ... "

আমি বুঝতে পারি কেন আমি ত্রুটি পাচ্ছি তবে ভাবছি এই প্রসঙ্গে তাদের সম্পর্কে আমার কিছু করা উচিত কিনা whether সংকলক সতর্কতাগুলি উপেক্ষা করা ভুল বলে মনে হচ্ছে।

আমি জানি আমি কোনও টাস্কের অপেক্ষায় এটি ঠিক করতে পারি un এটির মতো শোনা যাচ্ছে যে এটি মৃত্যুদন্ডে অপ্রয়োজনীয় ওভারহেড যুক্ত করবে তবে অ্যাসিঙ্ক কীওয়ার্ড উপস্থিত থাকায় এটি ইতিমধ্যে আছে কিনা তাও আমি নিশ্চিত নই।

আমি কি কেবল সতর্কতাগুলি উপেক্ষা করব বা এটিকে ঘিরে কাজ করার কোনও উপায় আছে যা আমি দেখছি না?


4
এটি নির্দিষ্টকরণের উপর নির্ভর করতে চলেছে। আপনি কি সত্যিই নিশ্চিত যে আপনি এই ক্রিয়াকলাপগুলি সিঙ্ক্রোনালি সম্পাদন করতে চান? আপনি যদি সেগুলি সিঙ্ক্রোনালি সম্পাদন করতে চান তবে কেন পদ্ধতিটি চিহ্নিত করা হচ্ছে async?
পরিবেশন করুন

11
শুধু asyncকীওয়ার্ডটি সরান । আপনি এখনও একটি Taskব্যবহার ফিরে আসতে পারেন Task.FromResult
মাইকেল লিউ

4
@ বেনভয়েগ্ট গুগল ওপ ইতিমধ্যে জানে না এমন ইভেন্টে এটি সম্পর্কে সম্পূর্ণ তথ্য রয়েছে।
পরিবেশন করুন

4
@ বেনভয়েট মাইকেল লিউ ইতিমধ্যে সেই ইঙ্গিতটি সরবরাহ করেন নি? ব্যবহার Task.FromResult

4
@ এইচভিডি: এটি পরে তাঁর মন্তব্যে সম্পাদিত হয়েছিল।
বেন ভয়েগট

উত্তর:


144

ASYNC শব্দ নিছক পদ্ধতির একটি বাস্তবায়ন বিস্তারিত হয়; এটি পদ্ধতি স্বাক্ষরের অংশ নয়। একটি বিশেষ পদ্ধতি বাস্তবায়ন বা ওভাররাইড অপেক্ষা করতে কিছুই না থাকে তবে শুধু বর্জন ASYNC শব্দ এবং ব্যবহার করে একটি সম্পূর্ণ টাস্ক আসতে Task.FromResult <TResult> :

public Task<string> Foo()               //    public async Task<string> Foo()
{                                       //    {
    Baz();                              //        Baz();
    return Task.FromResult("Hello");    //        return "Hello";
}                                       //    }

যদি আপনার পদ্ধতিটি টাস্ক <TResult> এর পরিবর্তে টাস্ক ফেরত দেয় তবে আপনি যে কোনও ধরণের এবং মানটির একটি সম্পন্ন টাস্কটি ফিরিয়ে দিতে পারেন। একটি জনপ্রিয় পছন্দ বলে মনে হচ্ছে:Task.FromResult(0)

public Task Bar()                       //    public async Task Bar()
{                                       //    {
    Baz();                              //        Baz();
    return Task.FromResult(0);          //
}                                       //    }

বা। নেট ফ্রেমওয়ার্ক ৪.6 অনুসারে, আপনি টাস্ক.কম্পলেটড টাস্কটি ফিরিয়ে দিতে পারেন :

public Task Bar()                       //    public async Task Bar()
{                                       //    {
    Baz();                              //        Baz();
    return Task.CompletedTask;          //
}                                       //    }

ধন্যবাদ আমি মনে করি আমি যে বিটটি হারিয়েছিলাম তা হ'ল আসল কীওয়ার্ড থাকার মতোই আপনার আসল কার্যটি ফিরিয়ে দেওয়ার পরিবর্তে একটি বাস্তব টাস্ক তৈরি করার ধারণাটি তৈরি হয়েছিল। এখন সুস্পষ্ট মনে হচ্ছে তবে আমি এটি দেখছিলাম না!
dannykay1710

4
এই কাজের জন্য টাস্ক লাইনের পাশাপাশি একটি স্থির সদস্যের সাথে টাস্ক করতে পারে mp অভিপ্রায়টি কিছুটা পরিষ্কার হবে এবং এই সমস্ত কর্তব্যতামূলক কাজগুলি ভাবতে আমার ব্যথা হয় যা কখনই প্রয়োজন হয় না এমন শূন্য ফিরে আসে।
রূপ্ট রাউসলে

await Task.FromResult(0)? কীভাবে await Task.Yield()?
সুশি 271

4
@ সুশি ২71১: না, অ- asyncপদ্ধতিতে আপনি অপেক্ষা না করে ফিরে আসেন Task.FromResult(0)
মাইকেল লিউ

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

16

এটি পুরোপুরি যুক্তিযুক্ত যে কিছু কিছু "অ্যাসিনক্রোনাস" অপারেশনগুলি সমকালীনভাবে সম্পূর্ণ হয়, তবুও বহুবর্ষের স্বার্থে অ্যাসিনক্রোনাস কল মডেলের সাথে সামঞ্জস্য করে।

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


4

আপনি কীভাবে সতর্কতা এড়াতে পারবেন সে সম্পর্কে আপনার প্রশ্নের উত্তরে মাইকেল লিউ উত্তর দিয়েছেন: টাস্কটি ফেরত দিয়ে rom

আমি আপনার প্রশ্নের "আমি কি সতর্কতার বিষয়ে চিন্তা করা উচিত" এর উত্তর দিতে যাচ্ছি।

উত্তরটি হল হ্যাঁ!

এর কারণ হ'ল সতর্কতাটি প্রায়শই ফলাফল করে যখন আপনি কোনও পদ্ধতি কল করেন Taskযা awaitঅপারেটর ব্যতীত একটি অ্যাসিঙ্ক পদ্ধতির অভ্যন্তরে ফিরে আসে । আমি সবেমাত্র একটি চুক্তিযুক্ত বাগটি ঠিক করেছি যা পূর্ববর্তী অপারেশনটির জন্য অপেক্ষা না করে সত্তা ফ্রেমওয়ার্কে একটি অপারেশন শুরু করেছি।

সংকলক সতর্কতা এড়ানোর জন্য আপনি যদি সাবধানে আপনার কোডটি লিখতে পারেন, তবে যখন কোনও সতর্কতা উপস্থিত থাকে, তখন এটি ব্যথার বুড়ো আঙ্গুলের মতো দাঁড়ায়। আমি কয়েক ঘন্টা ডিবাগ এড়াতে পারে।


4
এই উত্তরটি ঠিক ভুল। এখানে কেন: awaitপদ্ধতির ভিতরে কমপক্ষে একটি জায়গায় এক জায়গায় থাকতে পারে (কোনও CS1998 থাকবে না) তবে এর অর্থ এই নয় যে সংযোজন পদ্ধতির (ব্যবহার awaitবা অন্য কোনও ব্যবহারের জন্য ) অ্যাসিঙ্ক পদ্ধতির আর কোনও কল আসবে না । এখন যদি কেউ দুর্ঘটনাক্রমে আপনি সিঙ্ক্রোনাইজেশনটি মিস না করে তা নিশ্চিত করে কীভাবে তা জানতে চান তবে কেবলমাত্র নিশ্চিত হয়ে নিন যে আপনি আর কোনও সতর্কতা উপেক্ষা করবেন না - CS4014। এমনকি আমি এটিকে ত্রুটি হিসাবে হুমকি দেওয়ার পরামর্শ দেব would
ভিক্টর ইয়ারেমা

3

এটি অনেক দেরিতে হতে পারে তবে এটি কার্যকর তদন্ত হতে পারে:

সংকলিত কোড ( আইএল ) এর অভ্যন্তরীণ কাঠামো সম্পর্কে রয়েছে :

 public static async Task<int> GetTestData()
    {
        return 12;
    }

এটি আইএল-তে পরিণত হয়:

.method private hidebysig static class [mscorlib]System.Threading.Tasks.Task`1<int32> 
        GetTestData() cil managed
{
  .custom instance void [mscorlib]System.Runtime.CompilerServices.AsyncStateMachineAttribute::.ctor(class [mscorlib]System.Type) = ( 01 00 28 55 73 61 67 65 4C 69 62 72 61 72 79 2E   // ..(UsageLibrary.
                                                                                                                                     53 74 61 72 74 54 79 70 65 2B 3C 47 65 74 54 65   // StartType+<GetTe
                                                                                                                                     73 74 44 61 74 61 3E 64 5F 5F 31 00 00 )          // stData>d__1..
  .custom instance void [mscorlib]System.Diagnostics.DebuggerStepThroughAttribute::.ctor() = ( 01 00 00 00 ) 
  // Code size       52 (0x34)
  .maxstack  2
  .locals init ([0] class UsageLibrary.StartType/'<GetTestData>d__1' V_0,
           [1] valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32> V_1)
  IL_0000:  newobj     instance void UsageLibrary.StartType/'<GetTestData>d__1'::.ctor()
  IL_0005:  stloc.0
  IL_0006:  ldloc.0
  IL_0007:  call       valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<!0> valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32>::Create()
  IL_000c:  stfld      valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32> UsageLibrary.StartType/'<GetTestData>d__1'::'<>t__builder'
  IL_0011:  ldloc.0
  IL_0012:  ldc.i4.m1
  IL_0013:  stfld      int32 UsageLibrary.StartType/'<GetTestData>d__1'::'<>1__state'
  IL_0018:  ldloc.0
  IL_0019:  ldfld      valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32> UsageLibrary.StartType/'<GetTestData>d__1'::'<>t__builder'
  IL_001e:  stloc.1
  IL_001f:  ldloca.s   V_1
  IL_0021:  ldloca.s   V_0
  IL_0023:  call       instance void valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32>::Start<class UsageLibrary.StartType/'<GetTestData>d__1'>(!!0&)
  IL_0028:  ldloc.0
  IL_0029:  ldflda     valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32> UsageLibrary.StartType/'<GetTestData>d__1'::'<>t__builder'
  IL_002e:  call       instance class [mscorlib]System.Threading.Tasks.Task`1<!0> valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32>::get_Task()
  IL_0033:  ret
} // end of method StartType::GetTestData

এবং অ্যাসিঙ্ক এবং কার্য পদ্ধতি ছাড়াই:

 public static int GetTestData()
        {
            return 12;
        }

হয়ে:

.method private hidebysig static int32  GetTestData() cil managed
{
  // Code size       8 (0x8)
  .maxstack  1
  .locals init ([0] int32 V_0)
  IL_0000:  nop
  IL_0001:  ldc.i4.s   12
  IL_0003:  stloc.0
  IL_0004:  br.s       IL_0006
  IL_0006:  ldloc.0
  IL_0007:  ret
} // end of method StartType::GetTestData

আপনি এই পদ্ধতির মধ্যে বড় পার্থক্য দেখতে পাচ্ছিলেন। আপনি যদি অ্যাসিঙ্ক পদ্ধতির অভ্যর্থনা না ব্যবহার করেন এবং অ্যাসিঙ্ক পদ্ধতিটি ব্যবহারের বিষয়ে চিন্তা না করেন (উদাহরণস্বরূপ এপিআই কল বা ইভেন্ট হ্যান্ডলার) ভাল ধারণা এটিকে সাধারণ সিঙ্ক পদ্ধতিতে রূপান্তর করবে (এটি আপনার অ্যাপ্লিকেশন কার্যকারিতা সংরক্ষণ করে)।

আপডেট হয়েছে:

মাইক্রোসফ্ট ডক্স https://docs.microsoft.com/en-us/dotnet/standard/async-in-dthth থেকে অতিরিক্ত তথ্যও রয়েছে :

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


4
অতিরিক্ত হিসাবে আপনার ব্যবহারের চূড়ান্ত উপসংহারটি বিস্তৃতভাবে প্রশমিত করা হয়েছে async/awaitকারণ আপনি এটি সিপিইউ-আবদ্ধ একটি একক ক্রিয়াকলাপের আপনার অবাস্তব উদাহরণের উপর ভিত্তি করে চলেছেন । Tasks যখন সঠিকভাবে ব্যবহৃত হয়
তত্ক্ষণাতক

আমি কেবল এই পোস্টে বলেছি যা পরীক্ষার সরলিকৃত উদাহরণ। এছাড়াও আমি এপিআই এবং ইভেন্ট হেন্ডেলারদের অনুরোধ সম্পর্কে উল্লেখ করেছি যেখানে উভয় পদ্ধতির পদ্ধতিতে (async এবং নিয়মিত) ব্যবহারযোগ্য। এছাড়াও পিও ভিতরে অপেক্ষা না করে অ্যাসিঙ্ক পদ্ধতি ব্যবহার সম্পর্কে বলেছিলেন said আমার পোস্টটি এটি সম্পর্কে ছিল তবে সঠিকভাবে ব্যবহার সম্পর্কে নয় Tasks। এটি দুঃখজনক গল্প যে আপনি পোস্টের পুরো পাঠটি পড়ছেন না এবং দ্রুত সিদ্ধান্তে পৌঁছেছেন।
ওলেগ বোন্ডারেঙ্কো

4
যে পদ্ধতিটি ফিরে আসে int(যেমন আপনার ক্ষেত্রে আছে) এবং Taskওপি দ্বারা আলোচিত যেমন ফেরত দেওয়ার মধ্যে পার্থক্য রয়েছে । জিনিসগুলি ব্যক্তিগতভাবে না নিয়ে তার পোস্ট এবং গ্রহণযোগ্য উত্তরটি আবার পড়ুন Read আপনার উত্তর এই ক্ষেত্রে সহায়ক নয়। awaitভিতরে থাকা বা না থাকা পদ্ধতির মধ্যে পার্থক্য দেখাতেও আপনি বিরক্ত করবেন না। এখন আপনি যদি তা করে থাকেন তবে এটি একটি
উত্তরের পক্ষে

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

1

ফিরে আসার সময় ব্যতিক্রম আচরণের বিষয়ে নোট করুন Task.FromResult

এখানে একটি ছোট ডেমো যা চিহ্নিত এবং চিহ্নিত না হওয়া পদ্ধতির মধ্যে ব্যতিক্রম হ্যান্ডলিংয়ের পার্থক্য দেখায় async

public Task<string> GetToken1WithoutAsync() => throw new Exception("Ex1!");

// Warning: This async method lacks 'await' operators and will run synchronously. Consider ...
public async Task<string> GetToken2WithAsync() => throw new Exception("Ex2!");  

public string GetToken3Throws() => throw new Exception("Ex3!");
public async Task<string> GetToken3WithAsync() => await Task.Run(GetToken3Throws);

public async Task<string> GetToken4WithAsync() { throw new Exception("Ex4!"); return await Task.FromResult("X");} 


public static async Task Main(string[] args)
{
    var p = new Program();

    try { var task1 = p.GetToken1WithoutAsync(); } 
    catch( Exception ) { Console.WriteLine("Throws before await.");};

    var task2 = p.GetToken2WithAsync(); // Does not throw;
    try { var token2 = await task2; } 
    catch( Exception ) { Console.WriteLine("Throws on await.");};

    var task3 = p.GetToken3WithAsync(); // Does not throw;
    try { var token3 = await task3; } 
    catch( Exception ) { Console.WriteLine("Throws on await.");};

    var task4 = p.GetToken4WithAsync(); // Does not throw;
    try { var token4 = await task4; } 
    catch( Exception ) { Console.WriteLine("Throws on await.");};
}
// .NETCoreApp,Version=v3.0
Throws before await.
Throws on await.
Throws on await.
Throws on await.

( যখন জবাব অ্যাসিঙ্ক টাস্ক <T> ইন্টারফেস দ্বারা প্রয়োজনীয়, সংকলক সতর্কতা ছাড়াই কীভাবে রিটার্ন ভেরিয়েবল পাবেন ) এর জন্য আমার জবাবের ক্রস পোস্ট

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