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


156

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

আমি নীচের সতর্কতাটি কীভাবে সুন্দরভাবে দমন করব?

সতর্কতা 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
    // ...
}

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


1
তো, আপনি কি #pragmaসুন্দর মনে করেন না?
ফ্রিডরিক হামিদী

10
@ ফ্রাডেরিক হামিদি, আমি করি।
নাসেরটিও

2
@ নোসরটিও: আহ, ঠিক আছে। দুঃখিত, আমি ভেবেছিলাম এটি অন্য সতর্কতা ছিল। আমাকে উপেক্ষা কর!
জন স্কিটি 9

3
@ তেরিবাবাদ: আমি সত্যিই নিশ্চিত নই - বেশিরভাগ ক্ষেত্রে সতর্কতাটি বেশ যুক্তিসঙ্গত বলে মনে হয়। বিশেষত, আপনি যে কোনও ব্যর্থতার সাথে কী ঘটতে চান সে সম্পর্কে আপনার চিন্তা করা উচিত - সাধারণত "আগুন এবং ভুলে যান" এমনকি আপনার ব্যর্থতাগুলিতে কীভাবে লগ করা যায় ইত্যাদি সম্পর্কে আপনার কাজ করা উচিত
জোন স্কিট

4
@ তেরিবাবাদ, আপনি এটি অন্যভাবে ব্যবহার করার আগে, অ্যাসিঙ্ক পদ্ধতিতে কীভাবে ব্যতিক্রম প্রচার করা হয় সে সম্পর্কে আপনার স্পষ্ট চিত্র থাকা উচিত (এটি পরীক্ষা করুন )। তারপরে, @ Knaģis এর উত্তর সাহায্যকারী পদ্ধতির মাধ্যমে অগ্নি-বিস্মৃত হওয়ার জন্য কোনও ব্যতিক্রম না হারানোর একটি দুর্দান্ত উপায় সরবরাহ করে async void
নাকেরটিও

উত্তর:


160

সি # 7 এর সাহায্যে আপনি এখন ছাড়গুলি ব্যবহার করতে পারেন :

_ = WorkAsync();

7
এটি একটি সহজ সামান্য ভাষার বৈশিষ্ট্য যা আমি কেবল মনে করতে পারি না। _ = ...আমার মস্তিষ্কের মতো এটি ।
মার্ক এল।

3
আমি দেখতে পেলাম একটি সুপারপ্রেসেস আমার ভিজ্যুয়াল স্টুডিও "ত্রুটি তালিকা" থেকে আমার সতর্কবার্তাটি সরিয়ে ফেলেছে তবে "আউটপুট" নয় এবং #pragma warning disable CSxxxxফেলে দেওয়া থেকে আরও কুৎসিত দেখাচ্ছে;)
ডেভিড স্যাভেজ

122

আপনি এমন একটি এক্সটেনশন পদ্ধতি তৈরি করতে পারেন যা সতর্কতাটিকে প্রতিরোধ করবে। এক্সটেনশন পদ্ধতিটি খালি থাকতে পারে বা আপনি .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();
}

তবে এএসপি.এনইটি চলমান কাজগুলির সংখ্যা গণনা করে, তাই এটি 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));
}

8
আমি খুঁজে পেয়েছি TplExtensions.Forget। এর অধীনে আরও অনেক ধার্মিকতা রয়েছে Microsoft.VisualStudio.Threading। আমি আশা করি এটি ভিজ্যুয়াল স্টুডিও এসডিকে বাইরে ব্যবহারের জন্য উপলব্ধ করা হয়েছে।
নাসেরটিও

1
@ নোসরটিও এবং নাগিস, আমি এই পদ্ধতিটি পছন্দ করি এবং এটি ব্যবহার করার পরিকল্পনা করি। আমি সম্পর্কিত ফলো-আপ প্রশ্ন পোস্ট করেছি: স্ট্যাকওভারফ্লো
ম্যাট স্মিথ

3
@stricq কোন উদ্দেশ্যটি ভুলে যেতে () পরিবেশন করতে কনফিগারেশন ওয়েট (মিথ্যা) যুক্ত করবে? যেহেতু আমি এটি বুঝতে পারি, কনফিগারআওয়েট কেবলমাত্র সেই স্থানে থ্রেড সিঙ্ককে প্রভাবিত করে যেখানে অপেক্ষা একটি টাস্কে ব্যবহৃত হয়, তবে ফরগেট () এর উদ্দেশ্য হল টাস্কটি ফেলে দেওয়া, সুতরাং টাস্কটি কখনই প্রতীক্ষিত হতে পারে না, সুতরাং এখানে কনফিগারঅয়েট অর্থহীন।
dthorpe

3
যদি স্প্যানিং থ্রেডটি আগুনের আগে চলে যায় এবং ভুলে যাওয়া কাজটি সম্পূর্ণ হয়ে যায়, তবে কনফিগারআউট (মিথ্যা) ছাড়াই এটি নিজেই ফলের থ্রেডের দিকে মার্শাল করার চেষ্টা করবে, সেই থ্রেডটি গেছে তাই এটি অচল হয়ে পড়ে। কনফিগারঅয়েট (মিথ্যা) সেট করা সিস্টেমকে কলিং থ্রেডে মার্শাল না করতে বলে।
stricq

2
এই জবাবটিতে একটি নির্দিষ্ট কেস, এবং আরও কয়েক ডজন মন্তব্য পরিচালনা করার জন্য একটি সম্পাদনা রয়েছে। সহজভাবে জিনিসগুলি প্রায়শই সঠিক জিনিস হয়, ছাড়ের জন্য যান! এবং আমি @ fjch1997 উত্তরটি উদ্ধৃত করেছি: একটি সতর্কতা দমন করার উদ্দেশ্যে, এমন একটি পদ্ধতি তৈরি করা বোকামি যা কার্যকর করতে আরও কয়েকটি টিক লাগে।
তেজয়

39

আপনি নিম্নলিখিত বৈশিষ্ট্যটি সহ পদ্ধতিটি সাজাতে পারেন:

[System.Diagnostics.CodeAnalysis.SuppressMessage("Await.Warning", "CS4014:Await.Warning")]
static async Task StartWorkAsync()
{
    WorkAsync();
    // ...
}

মূলত আপনি সংকলককে বলছেন যে আপনি কী করছেন তা আপনি জানেন এবং এটির সম্ভাব্য ভুল সম্পর্কে চিন্তা করার দরকার নেই।

এই কোডটির গুরুত্বপূর্ণ অংশটি হ'ল দ্বিতীয় প্যারামিটার। "CS4014:" অংশটি হ'ল সতর্কতাটিকে দমন করে। আপনি বাকী যা কিছু লিখতে পারেন।


আমার পক্ষে কাজ করে না: ম্যাক 7.0.1 এর জন্য ভিজ্যুয়াল স্টুডিও (বিল্ড 24)। মনে হয় এটি করা উচিত কিন্তু - না।
আয়রনড

1
[SuppressMessage("Compiler", "CS4014")]ত্রুটি তালিকার উইন্ডোতে বার্তাটি দমন করে তবে আউটপুট উইন্ডোটি এখনও একটি সতর্কতা রেখা দেখায়
ডেভিড চিং

35

এটির সাথে আমার দু'টি উপায় way

এটিকে একটি বিলোপযুক্ত চলকটিতে সংরক্ষণ করুন (সি # 7)

উদাহরণ

_ = Task.Run(() => DoMyStuff()).ConfigureAwait(false);

C # 7 এ ছাড়ার প্রচলন হওয়ার পরে, আমি এখন এটিকে সতর্কতা দমন করার চেয়ে ভাল বলে মনে করি। কারণ এটি কেবল সতর্কবার্তাটিকেই দমন করে না, তবে আগুন এবং ভুলে যাওয়া অভিপ্রায়ও স্পষ্ট করে তোলে।

তদুপরি, সংকলক রিলিজ মোডে এটি অপ্টিমাইজ করতে সক্ষম হবে।

শুধু এটি দমন

#pragma warning disable 4014
...
#pragma warning restore 4014

"আগুন এবং ভুলে যাও" একটি দুর্দান্ত যথেষ্ট সমাধান।

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

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

সর্বেসর্বা

এমন একটি পদ্ধতি তৈরি করা বোকামি যা কেবলমাত্র একটি সতর্কতা দমন করার উদ্দেশ্যে, কার্যকর করতে আরও কয়েকটি টিক লাগে।


এটি ম্যাক 7.0.1 (বিল্ড 24) এর জন্য ভিজ্যুয়াল স্টুডিওতে কাজ করেছে।
আয়রনড রড

1
এমন একটি পদ্ধতি তৈরি করা বোকামি যা কেবলমাত্র একটি সতর্কতা দমনের উদ্দেশ্যেই কার্যকর করতে আরও কয়েকটি টিক লাগে takes এটি কোনও অতিরিক্ত টিক যোগ করে না এবং আইএমও আরও পঠনযোগ্য:[MethodImpl(MethodImplOptions.AggressiveInlining)] void Forget(this Task @this) { } /* ... */ obj.WorkAsync().Forget();
নাসারটিও

1
@ নোসেরাটিও অনেক সময় যখন আমি সংকলকটি ব্যবহার করি AggressiveInliningকেবল যে কোনও কারণেই এটি উপেক্ষা করে
fjch1997

1
আমি প্রাগমা বিকল্পটি পছন্দ করি কারণ এটি অত্যন্ত সহজ এবং কেবলমাত্র বর্তমান পদ্ধতিতে (বা বিভাগের) কোডের প্রয়োগ হয়, পুরো পদ্ধতি নয়।
wasatchwizard

2
ত্রুটি কোডটি ব্যবহার করতে #pragma warning disable 4014এবং তারপরে সতর্কতাটি পরে পুনরুদ্ধার করতে ভুলবেন না #pragma warning restore 4014। এটি ত্রুটি কোড ব্যতীত এখনও কাজ করে, তবে আপনি ত্রুটি নম্বরটি যুক্ত না করলে এটি সমস্ত বার্তা দমন করে।
ডানিংক্রুজারএফেক্ট

11

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

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); 
}

আমি প্রশ্নটিতে এই পদ্ধতির কথা উল্লেখ করেছি, যাদের মধ্যে আমি বিশেষভাবে পছন্দ করি না as
নাসেরটিও

উপস! এটি লক্ষ্য করা যায় নি কারণ এটি আপনার প্রাগমা হিসাবে একই কোড বিভাগে ছিল ... এবং আমি উত্তরগুলি খুঁজছিলাম। এটি বাদ দিয়ে, আপনি এই পদ্ধতিটি পছন্দ করেন না তা কি?
নেলিলেস

1
আমি taskভুলে যাওয়া স্থানীয় ভেরিয়েবলের মতো দেখতে এটি পছন্দ করি না । প্রায় কম্পাইলারের মতো আমাকে আরও একটি সতর্কতা দেওয়া উচিত, " taskঅ্যাসাইন করা হয় তবে এর মানটি কখনই ব্যবহৃত হয় না" ছাড়াও এটি ব্যবহার করে না। এছাড়াও, এটি কোডটি কম পাঠযোগ্য করে তোলে। আমি নিজেই এই পদ্ধতির ব্যবহার করি ।
নাসেরটিও

যথেষ্ট উপযুক্ত - আমার একটি অনুরূপ অনুভূতি ছিল যার কারণে আমি এটির নাম রাখি fireAndForget... সুতরাং আমি আশা করি এটি এখন থেকে অবাস্তব হবে।
noelicus

4

সতর্কতার কারণ হ'ল ওয়ার্কএন্সেঙ্ক এমন একটি ফিরিয়ে দিচ্ছে Taskযা কখনও পড়া হয় না বা প্রতীক্ষিত হয় না। আপনি ওয়ার্কএন্সেঙ্কের রিটার্ন টাইপ সেট করতে পারেন 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); 
}

2

কেন এটি অ্যাসিঙ্ক পদ্ধতির অভ্যন্তরে জড়ো করা যায় না যা শূন্য হয়? কিছুটা লম্বা তবে সমস্ত ভেরিয়েবল ব্যবহার করা হয়।

static async Task StartWorkAsync()
{   
     async void WorkAndForgetAsync() => await WorkAsync();
     WorkAndForgetAsync(); // no warning
}

1

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

    delegate Task IntermediateHandler();



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

এবং এটি যেমন কল

(new IntermediateHandler(AsyncOperation))();

...

আমি ভেবেছিলাম এটি আকর্ষণীয় যে কম্পাইলার ডেলিগেট ব্যবহার করার সময় ঠিক একই সতর্কতা দেয় না।


কোনও প্রতিনিধি ঘোষণার দরকার নেই, আপনি সম্ভবত (new Func<Task>(AsyncOperation))()এটি করতে পারেন যদিও আইএমও এটি এখনও কিছুটা ভারবস।
নাসেরটিও
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.