c# - "সতর্কবার্তা CS4014 দমন করা হচ্ছে: কারণ এই কলটি অপেক্ষা করা হচ্ছে না, বর্তমান পদ্ধতি কার্যকর করা চলছে..."




async-await (6)

C # 7 দিয়ে আপনি এখন discards ব্যবহার করতে পারেন:

_ = WorkAsync();

এটি "কোনও অপেক্ষা না করে # এভাবে অ্যাসাইন পদ্ধতিটি নিরাপদভাবে কল করতে" এর সদৃশ নয়।

কিভাবে আমি চমত্কারভাবে নিম্নলিখিত সতর্কতা দমন করবেন?

সতর্কতা CS4014: এই কলটি অপেক্ষা করা হয় না, কারণ কলটি সম্পন্ন হওয়ার আগে বর্তমান পদ্ধতি কার্যকর করা চলতে থাকে। কলটির ফলাফলের জন্য 'অপেক্ষা' অপারেটর প্রয়োগ করার কথা বিবেচনা করুন।

একটি সহজ উদাহরণ:

static async Task WorkAsync()
{
    await Task.Delay(1000);
    Console.WriteLine("Done!");
}

static async Task StartWorkAsync()
{
    WorkAsync(); // I want fire-and-forget 

    // more unrelated async/await stuff here, e.g.:
    // ...
    await Task.Delay(2000); 
}

আমি কি চেষ্টা এবং পছন্দ না:

static async Task StartWorkAsync()
{
    #pragma warning disable 4014
    WorkAsync(); // I want fire-and-forget here
    #pragma warning restore 4014
    // ...
}

static async Task StartWorkAsync()
{
    var ignoreMe = WorkAsync(); // I want fire-and-forget here
    // ...
}

আপডেট করা হয়েছে , মূল গৃহীত উত্তরটি সম্পাদিত হওয়ার পরে, আমি C # 7.0 বাতিলের মাধ্যমে গ্রহণযোগ্য উত্তরটি পরিবর্তন করেছি, কারণ আমি মনে করি না যে ContinueWith এখানে উপযুক্ত। যখনই আমাকে ফায়ার-ও-ভুলে যাওয়া ক্রিয়াকলাপগুলির জন্য ব্যতিক্রমগুলি লগ ইন করতে হবে, আমি এখানে স্টিফেন ক্ল্যারির প্রস্তাবিত আরও বিস্তৃত পদ্ধতি ব্যবহার করব।


আপনি একটি এক্সটেনশন পদ্ধতি তৈরি করতে পারেন যা সতর্কতা প্রতিরোধ করবে। এক্সটেনশান পদ্ধতি খালি হতে পারে অথবা আপনি ব্যতিক্রম হ্যান্ডলিং যুক্ত করতে পারেন।

static class TaskExtensions
{
    public static void Forget(this Task task)
    {
        task.ContinueWith(
            t => { WriteLog(t.Exception); },
            TaskContinuationOptions.OnlyOnFaulted);
    }
}

public async Task StartWorkAsync()
{
    this.WorkAsync().Forget();
}

তবে ASP.NET চলমান কাজগুলির সংখ্যা গণনা করে, তাই এটি উপরে তালিকাভুক্ত করা সহজ Forget() এক্সটেনশানটির সাথে কাজ করবে না এবং এর পরিবর্তে ব্যতিক্রমটি ব্যর্থ হতে পারে:

একটি অ্যাসিঙ্ক্রোনাস মডিউল বা হ্যান্ডলার সম্পন্ন যখন একটি অ্যাসিঙ্ক্রোনাস অপারেশন এখনও মুলতুবি ছিল।

.NET 4.5.2 দিয়ে এটি সমাধান করা যেতে পারে HostingEnvironment.QueueBackgroundWorkItem :

public static Task HandleFault(this Task task, CancellationToken cancelToken)
{
    return task.ContinueWith(
        t => { WriteLog(t.Exception); },
        cancelToken,
        TaskContinuationOptions.OnlyOnFaulted,
        TaskScheduler.Default);
}

public async Task StartWorkAsync()
{
    System.Web.Hosting.HostingEnvironment.QueueBackgroundWorkItem(
        cancelToken => this.WorkAsync().HandleFault(cancelToken));
}

আমি আজ দুর্ঘটনা দ্বারা এই পদ্ধতির পাওয়া। আপনি একটি প্রতিনিধি নির্ধারণ করতে পারেন এবং প্রথম প্রতিনিধি হিসাবে অ্যাসাইন পদ্ধতি নির্ধারণ করতে পারেন।

    delegate Task IntermediateHandler();



    static async Task AsyncOperation()
    {
        await Task.Yield();
    }

এবং তাই এটি কল

(new IntermediateHandler(AsyncOperation))();

...

আমি এটা মজার ছিল যে কম্পাইলার delegate ব্যবহার করার সময় সঠিক একই সতর্কতা দেবে না।


এই সঙ্গে ডিল করার আমার দুটি উপায়।

শুধু এটা দমন

#pragma warning disable 4014 "অগ্নি এবং ভুলে যাওয়া" এর একটি চমৎকার যথেষ্ট সমাধান।

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

#pragma warning disable 4014 কীভাবে বানানটি মনে রাখা আপনার সমস্যা হয়েছে, কেবল ভিজ্যুয়াল স্টুডিওটিকে আপনার জন্য যুক্ত করুন। Ctrl + টিপুন। "দ্রুত পদক্ষেপ" খুলতে এবং তারপরে "CS2014 চাপুন"

একটি স্থানীয় পরিবর্তনশীল এটি সংরক্ষণ করুন

উদাহরণ

var task = Task.Run(() => DoMyStuff()).ConfigureAwait(false);

যেহেতু task কোনও পরবর্তী কল নেই, তাই রিলিজ মোডে স্থানীয় ভেরিয়েবলটিকে অবিলম্বে ঠিক মতোই অপ্টিমাইজ করা উচিত। আসলে, আমি কম্পাইলার স্থানীয় ভেরিয়েবল তৈরি করতেও সন্দেহ করবো (কেউ এটি ডিকম্প্লেলারের সাথে নিশ্চিত করতে পারে)।

সর্বেসর্বা

এটি এমন একটি পদ্ধতি তৈরি করা মূঢ় যা চালানোর জন্য আরও কয়েকটি টিট নেয়, শুধুমাত্র একটি সতর্কতা দমন করার উদ্দেশ্যে।


সতর্কবার্তা বন্ধ করার একটি সহজ উপায় কেবল কল করার সময় কার্য বরাদ্দ করা:

Task fireAndForget = WorkAsync(); // No warning now

এবং তাই আপনার মূল পোস্টে আপনি করবেন:

static async Task StartWorkAsync()
{
    // Fire and forget
    var fireAndForget = WorkAsync(); // Tell the compiler you know it's a task that's being returned 

    // more unrelated async/await stuff here, e.g.:
    // ...
    await Task.Delay(2000); 
}

সতর্কবার্তাটির কারণ হল WorkAsync কোনও কাজটি ফেরত দিচ্ছে যা কখনও পড়তে বা প্রতীক্ষিত হয় না। আপনি রিটার্ন টাইপের WorkAsyncটি void এবং সতর্কতাটি চলে যাবে।

কলারের কর্মীর অবস্থা জানতে হলে সাধারণত একটি পদ্ধতি একটি Task প্রদান করে। ফায়ার-ও-ভুলে যাওয়ার ক্ষেত্রে, আহ্বানকারীকে বলা হয় যে আহ্বানকারী কল পদ্ধতির থেকে আলাদা।

static async void WorkAsync()
{
    await Task.Delay(1000);
    Console.WriteLine("Done!");
}

static async Task StartWorkAsync()
{
    WorkAsync(); // no warning since return type is void

    // more unrelated async/await stuff here, e.g.:
    // ...
    await Task.Delay(2000); 
}




async-await