একটি অকার্যকর async পদ্ধতির জন্য অপেক্ষা করুন


155

কোনও void asyncপদ্ধতির কাজ শেষ করার জন্য আমি কীভাবে অপেক্ষা করতে পারি ?

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

async void LoadBlahBlah()
{
    await blah();
    ...
}

এখন আমি নিশ্চিত করতে চাই যে অন্য কোথাও চালিয়ে যাওয়ার আগে সবকিছু লোড হয়েছে।

উত্তর:


234

সেরা অনুশীলন হ'ল ফাংশনটি async voidকেবল আগুন এবং পদ্ধতিটি ভুলে গেলে চিহ্নিত করা, আপনি যদি অপেক্ষা করতে চান তবে আপনার এটি হিসাবে চিহ্নিত করা উচিত async Task

যদি আপনি এখনও অপেক্ষা করতে চান, তবে এটির মতো মোড়ানো করুন await Task.Run(() => blah())


ব্লেইহ স্পষ্টতই টাস্কটি ফিরিয়ে দিচ্ছে এবং হ্যা অ্যাসিঙ্ক স্বাক্ষর কেন আপনি অপেক্ষা না করে এটিকে ডাকবেন। এমনকি ভিএস আপনাকে এ সম্পর্কে সতর্কতা দেবে।
ব্যাটমাই

8
await Task.Run(() => An_async_void_method_I_can_not_modify_now())
থিমফিল্ড

1
await Task.Run(() => blah())বিভ্রান্তিকর। এটি অ্যাসিঙ্ক ফাংশন সমাপ্তির অপেক্ষায় নয় blah, এটি কেবলমাত্র (তুচ্ছ) কাজটি তৈরির অপেক্ষায় রয়েছে এবং blah()এটি সম্পন্ন হওয়ার সাথে সাথেই অব্যাহত থাকে ।
জোনাথন লিডব্যাক

@JonathanLidbeck বিবৃতি "অবিলম্বে চলতে সামনে বাজে ভুল চেষ্টা করুন।" অপেক্ষায় রয়েছেন Task.Run (() => Thread.Sleep (10_000)) ", কাজের কোনো পরের লাইনে চালানোর আগে 10 সেকেন্ডের + + জন্য প্রতীক্ষিত হয়
রোহিত শর্মা

@ রোহিতশর্মা, এটি আপনার উদাহরণের জন্য সঠিক, তবে অ্যাসিঙ্ক Thread.Sleepনয়। এই প্রশ্নটি একটি async voidঅনুষ্ঠানের অপেক্ষার বিষয়ে , বলুনasync void blah() { Task.Delay(10000); }
জোনাথন লিডবেক

59

আপনি যদি নিজের ফাংশনের স্বাক্ষরটিকে এখানে পরিবর্তন করতে পারেন async Taskতবে আপনি এখানে উপস্থাপিত কোডটি ব্যবহার করতে পারেন


27

সবচেয়ে ভাল সমাধানটি ব্যবহার করা async Task। আপনার async voidবেশ কয়েকটি কারণে এড়ানো উচিত , যার মধ্যে একটি হ'ল সামঞ্জস্যযোগ্যতা।

যদি পদ্ধতিটি ফিরে আসতে না পারে Task(উদাহরণস্বরূপ, এটি কোনও ইভেন্ট হ্যান্ডলার), তবে আপনি SemaphoreSlimযখন প্রস্থান করতে চলেছেন তখন আপনি পদ্ধতি সংকেতটি ব্যবহার করতে পারেন। এটি একটি finallyব্লক করে বিবেচনা করুন ।


1

একটি অটোসেটসেন্ট করুন, ফাংশনটি কল করুন এবং তারপরে অটোসেটসেন্ট এ অপেক্ষা করুন এবং তারপরে এটি অ্যাসিঙ্ক শূন্যের মধ্যে সেট করুন যখন আপনি জানেন যে এটি সম্পন্ন হয়েছে।

আপনি এমন কোনও কার্যের জন্যও অপেক্ষা করতে পারেন যা আপনার অকার্যকর async থেকে ফিরে আসে


1

আপনাকে ম্যানুয়ালি সত্যিই কিছু করার দরকার নেই, awaitকীওয়ার্ড blah()ফিরিয়ে না দেওয়া পর্যন্ত ফাংশন সম্পাদনকে বিরতি দেয়।

private async void SomeFunction()
{
     var x = await LoadBlahBlah(); <- Function is not paused
     //rest of the code get's executed even if LoadBlahBlah() is still executing
}

private async Task<T> LoadBlahBlah()
{
     await DoStuff();  <- function is paused
     await DoMoreStuff();
}

Tঅবজেক্ট blah()রিটার্নের ধরণ

আপনি সত্যিই awaitকোনও voidফাংশন LoadBlahBlah()করতে পারবেন না তাই হতে পারে নাvoid


আমি অপেক্ষা করতে চান LoadBlahBlah(), শেষ নাblah()
MBZ

10
দুর্ভাগ্যক্রমে
অ্যাসিঙ্ক শূন্য

-1

আমি জানি এটি একটি পুরানো প্রশ্ন, তবে এটি এখনও একটি সমস্যা যা আমি প্রবেশ করি এবং এখনও অ্যাসিঙ্ক / অ্যাসিঙ্ক অকার্যকর স্বাক্ষর পদ্ধতিতে অপেক্ষা করার সময় এটি সঠিকভাবে করার কোনও সুস্পষ্ট সমাধান এখনও পাওয়া যায় না।

যাইহোক, আমি লক্ষ্য করেছি যে। ওয়েট () শূন্য পদ্ধতিতে সঠিকভাবে কাজ করছে।

এবং যেহেতু অ্যাসিঙ্ক অকার্যকর এবং অকার্যকর একই স্বাক্ষর রয়েছে, আপনার নিম্নলিখিতগুলি করতে হবে।

void LoadBlahBlah()
{
    blah().Wait(); //this blocks
}

বিভ্রান্তিমূলকভাবে পর্যাপ্ত async / প্রতীক্ষা পরবর্তী কোডটিতে ব্লক করে না।

async void LoadBlahBlah()
{
    await blah(); //this does not block
}

আপনি যখন আপনার কোডটি ছিন্ন করেন, তখন আমার অনুমান যে অ্যাসিঙ্ক শূন্যতা একটি অভ্যন্তরীণ টাস্ক তৈরি করে (ঠিক তেমনি অ্যাসিঙ্ক টাস্ক), তবে যেহেতু স্বাক্ষরটি অভ্যন্তরীণ টাস্কগুলি ফিরিয়ে আনতে সমর্থন করে না

এর অর্থ হ'ল অভ্যন্তরীণভাবে async শূন্য পদ্ধতিটি অভ্যন্তরীণভাবে async পদ্ধতিগুলি "অপেক্ষা" করতে সক্ষম হবে। কিন্তু অভ্যন্তরীণ টাস্কটি কখন সম্পূর্ণ হয় তা বাহ্যিকভাবে জানতে অক্ষম।

সুতরাং আমার উপসংহারটি হ'ল async অকার্যকর উদ্দেশ্য হিসাবে কাজ করছে, এবং যদি আপনার অভ্যন্তরীণ টাস্কের কাছ থেকে প্রতিক্রিয়া প্রয়োজন হয় তবে তার পরিবর্তে আপনাকে async কার্য স্বাক্ষর ব্যবহার করতে হবে।

আশা করি আমার ঝাঁকুনি উত্তরটি সন্ধানের জন্য কারও কাছে বোধগম্য হবে।

সম্পাদনা করুন: আমি কিছু উদাহরণ কোড তৈরি করেছি এবং এটি কী ঘটছে তা দেখার জন্য এটি সংক্ষেপিত করেছি।

static async void Test()
{
    await Task.Delay(5000);
}

static async Task TestAsync()
{
    await Task.Delay(5000);
}

রূপান্তরিত হয় (সম্পাদনা: আমি জানি যে বডি কোডটি এখানে নয় তবে স্টেটম্যাচাইনে রয়েছে, তবে স্টেটম্যাচিনগুলি মূলত অভিন্ন ছিল, তাই আমি এগুলি যুক্ত করতে বিরত হই নি)

private static void Test()
{
    <Test>d__1 stateMachine = new <Test>d__1();
    stateMachine.<>t__builder = AsyncVoidMethodBuilder.Create();
    stateMachine.<>1__state = -1;
    AsyncVoidMethodBuilder <>t__builder = stateMachine.<>t__builder;
    <>t__builder.Start(ref stateMachine);
}
private static Task TestAsync()
{
    <TestAsync>d__2 stateMachine = new <TestAsync>d__2();
    stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
    stateMachine.<>1__state = -1;
    AsyncTaskMethodBuilder <>t__builder = stateMachine.<>t__builder;
    <>t__builder.Start(ref stateMachine);
    return stateMachine.<>t__builder.Task;
}

AsyncVoidMethodBuilder বা AsyncTaskMethodBuilder আসলেই স্টার্ট পদ্ধতিতে এমন কোনও কোড নেই যা তাদের ব্লক করার ইঙ্গিত দেয় এবং এগুলি শুরু হওয়ার পরে সর্বদা অ্যাসিঙ্ক্রোনালি চালিত হয়।

অর্থ ফেরত টাস্ক ব্যতীত, এটি সম্পূর্ণ কিনা তা যাচাই করার উপায় নেই।

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

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

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