CS1998 সতর্কবার্তাটি দমন করুন: এই অ্যাসিঙ্ক পদ্ধতিতে 'অপেক্ষা' নেই


104

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

অ্যাসিঙ্ক ফাংশনে অপেক্ষা না করার সময়।

বার্তাটি দমন করা কি সম্ভব?

public async Task<object> test()
{
    throw new NotImplementedException();
}

সতর্কতা CS1998: এই অ্যাসিঙ্ক পদ্ধতিতে অপেক্ষাকৃত অপারেটরগুলির অভাব রয়েছে এবং এটি সিঙ্ক্রোনালি চলবে। অ-ব্লকিং এপিআই কলগুলির অপেক্ষার জন্য 'অপেক্ষার' অপারেটরটি ব্যবহার করুন বা কোনও ব্যাকগ্রাউন্ড থ্রেডে সিপিইউ-আবদ্ধ কাজ করতে 'টাস্ক.রুন (...)' অপেক্ষা করুন।


1
অ্যাসিঙ্ক হিসাবে চিহ্নিত ফাংশনে নতুন অপেক্ষার কীওয়ার্ডটি ব্যবহার করবেন না।
সাইমন

কীভাবে আমাদের এমন একটি কোড নমুনা দেখানো যা সমস্যাটি পুনরুত্পাদন করে?
জন স্যান্ডার্স

এটি দেখুন: আমার
এস.সর্পুশন

উত্তর:


106

আমি কিছু অ্যাসিঙ্ক ফাংশন সহ একটি ইন্টারফেস পেয়েছি।

পদ্ধতিগুলি ফিরছে Task, আমি বিশ্বাস করি।asyncএটি একটি বাস্তবায়ন বিশদ, সুতরাং এটি ইন্টারফেস পদ্ধতিতে প্রয়োগ করা যায় না।

ইন্টারফেস প্রয়োগ করে এমন কিছু শ্রেণীর জন্য অপেক্ষা করার মতো কিছু নেই, এবং কিছু কিছু কেবল ফেলে দিতে পারে।

এই ক্ষেত্রে, আপনি asyncবাস্তবায়নের বিশদ এটির সুযোগটি নিতে পারেন ।

আপনার যদি কিছু না থাকে awaitতবে আপনি কেবল ফিরে আসতে পারেন Task.FromResult:

public Task<int> Success() // note: no "async"
{
  ... // non-awaiting code
  int result = ...;
  return Task.FromResult(result);
}

নিক্ষেপের ক্ষেত্রে NotImplementedException, পদ্ধতিটি আরও কিছুটা স্পষ্ট:

public Task<int> Fail() // note: no "async"
{
  var tcs = new TaskCompletionSource<int>();
  tcs.SetException(new NotImplementedException());
  return tcs.Task;
}

আপনার যদি নিক্ষেপ করার প্রচুর পদ্ধতি থাকে NotImplementedException(যা নিজেই ইঙ্গিত দিতে পারে যে কিছু নকশা-স্তরের রিফ্যাক্টরিং ভাল হবে), তবে আপনি শব্দবন্ধকে একটি সহায়ক শ্রেণিতে গুটিয়ে রাখতে পারেন:

public static class TaskConstants<TResult>
{
  static TaskConstants()
  {
    var tcs = new TaskCompletionSource<TResult>();
    tcs.SetException(new NotImplementedException());
    NotImplemented = tcs.Task;
  }

  public static Task<TResult> NotImplemented { get; private set; }
}

public Task<int> Fail() // note: no "async"
{
  return TaskConstants<int>.NotImplemented;
}

সহায়ক শ্রেণিও জিসিকে অন্যভাবে সংগ্রহ করতে হবে এমন আবর্জনা হ্রাস করে, যেহেতু একই রিটার্ন টাইপের প্রতিটি পদ্ধতি তার ভাগ করতে পারে Task এবংNotImplementedException বিষয়গুলি পারে।

আমার এ্যাসএনএক্সএক্স লাইব্রেরিতে আমার কাছে আরও কয়েকটি "টাস্ক ধ্রুবক" টাইপের উদাহরণ রয়েছে


1
আমি কীওয়ার্ডটি হারাতে ভেবে দেখিনি। আপনি যেমনটি বলেছেন, async ইন্টারফেসের সাথে কিছুই করার নেই। আমার খারাপ, আপনাকে ধন্যবাদ।
সাইমন

3
আপনি কি এমন পদ্ধতির প্রস্তাব দিতে পারেন যেখানে রিটার্নের ধরণটি কেবল টাস্ক (ফলাফল ছাড়াই?)
মাইক

9
সতর্কতা: এই পদ্ধতির ফলে সমস্যা দেখা দিতে পারে কারণ ত্রুটিগুলি আপনার প্রত্যাশার মতো প্রচারিত হবে না। সাধারণত কলার আপনার পদ্ধতিতে একটি ব্যতিক্রমের মধ্যে প্রকাশিত হবে বলে আশা করবে Task। পরিবর্তে, এটি তৈরি করার সুযোগ পাওয়ার আগে আপনার পদ্ধতিটি ছুঁড়ে ফেলবে Task। আমি সত্যিই মনে করি সেরা প্যাটার্ন হ'ল asyncকোনও অপারেটরবিহীন কোনও পদ্ধতি নির্ধারণ করা await। এটি পদ্ধতিটির মধ্যে কোডটি সমস্তটির অংশ হিসাবে বিবেচিত হবে তা নিশ্চিত করে Task
বব মায়ার্স

11
CS1998 এড়াতে, আপনি await Task.FromResult(0);আপনার পদ্ধতিতে যুক্ত করতে পারেন । এটির কোনও কার্যকর পার্ফ ইফেক্ট (টাস্ক.ইয়েল্ড () এর বিপরীতে হওয়া উচিত নয়)।
বব মায়ার্স

3
@ অ্যান্ড্রু থেকেন: এই দিনগুলিতে আপনি কেবলমাত্র করতে পারেন return Task.CompletedTask;- সর্বোত্তমতম।
স্টিফেন ক্লিয়ারি

63

আর একটি বিকল্প, যদি আপনি ফাংশনটির বডিটি সহজ রাখতে চান এবং সমর্থন করার জন্য কোড না লিখে থাকেন, তবে কেবল # প্রগ্রমা দিয়ে সতর্কতা দমন করা:

#pragma warning disable 1998
public async Task<object> Test()
{
    throw new NotImplementedException();
}
#pragma warning restore 1998

যদি এটি যথেষ্ট সাধারণ হয় তবে আপনি অক্ষম বিবৃতিটি ফাইলের শীর্ষে রাখতে পারেন এবং পুনরুদ্ধারটি বাদ দিতে পারেন।

http://msdn.microsoft.com/en-us/library/441722ys(v=vs.110).aspx


40

অ্যাসিঙ্ক কীওয়ার্ড সংরক্ষণের আরেকটি উপায় (আপনি যদি এটি রাখতে চান তবে) ব্যবহার করা হয়:

public async Task StartAsync()
{
    await Task.Yield();
}

একবার আপনি পদ্ধতিটি জনপ্রিয় করুন আপনি কেবল বিবৃতিটি সরিয়ে ফেলতে পারেন। আমি এটি প্রচুর ব্যবহার করি বিশেষত যখন কোনও পদ্ধতিতে কোনও কিছুর জন্য অপেক্ষা করা যেতে পারে তবে প্রতিটি বাস্তবায়ন আসলে ঘটে না।


এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। কখনও কখনও ইন্টারফেস বাস্তবায়নগুলি অ্যাসিঙ্ক হওয়ার দরকার হয় না, এটি একটি Task.Runকলটিতে সমস্ত মোড়ানো থেকে পরিষ্কার is
অ্যান্ড্রু থেকেন

12
Task.CompletedTask এর জন্য অপেক্ষা করুন; // আরও ভাল বিকল্প হতে পারে
ফ্রোড নীলসেন

@ ফ্রোডনিলসেনের কোনও কারণে Task.CompletedTaskআর অস্তিত্ব নেই বলে মনে হয়।
সেবাস্তিয়ান ভ্যানস্টিনকিস্ট

1
@ সেবাস্তিয়ানভান্সটেনকিস্টে। নেট ফ্রেমওয়ার্ক 4.6->, ইউডাব্লুপি 1.0->, নেট কোর 1.0->
ফ্রয়েড নীলসেন

1
@ অ্যান্ড্রু থেক এই সিদ্ধান্তে পৌঁছাতে আমার কিছুটা সময় লেগেছে যে এই উত্তর এবং আপনার মন্তব্য বিশেষত প্রয়োগের ক্ষেত্রে প্রয়োগ হয় যেখানে বাস্তবায়ন ফাঁকা থাকে বা কেবল ব্যতিক্রম ছুঁড়ে ফেলে (মূল প্রশ্নের মতো)। যদি একটি বাস্তবায়ন কোনও মান দেয় তবে মনে Task.FromResultহয় এটি আরও ভাল উত্তর। যে বিষয়টি, আপনি যদি হয় একটি ব্যতিক্রম নিক্ষেপ করবে, মনে অন্য উত্তর সংক্রান্ত খেলার মধ্যে এসে গেছে Task.FromExceptionএই আদর্শ সমাধান না করে। তুমি কি রাজি?
BlueMonkMN

15

সমাধানগুলি এবং কঠোরভাবে বলার মধ্যে পার্থক্য রয়েছে আপনার জানা উচিত যে কলার কীভাবে অ্যাসিঙ্ক পদ্ধতিটি কল করতে চলেছেন, কিন্তু ডিফল্ট ব্যবহারের ধরণ যা ধরে নিয়েছে "।উইট ()" পদ্ধতির ফলাফলের উপরে - " রিটার্ন টাস্ক। কমপ্লিটড টাস্ক " সেরা সমাধান।

    BenchmarkDotNet=v0.10.11, OS=Windows 10 Redstone 3 [1709, Fall Creators Update] (10.0.16299.192)
Processor=Intel Core i5-2500K CPU 3.30GHz (Sandy Bridge), ProcessorCount=4
Frequency=3233537 Hz, Resolution=309.2589 ns, Timer=TSC
.NET Core SDK=2.1.2
  [Host] : .NET Core 2.0.3 (Framework 4.6.25815.02), 64bit RyuJIT
  Clr    : .NET Framework 4.7 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.2600.0
  Core   : .NET Core 2.0.3 (Framework 4.6.25815.02), 64bit RyuJIT


         Method |  Job | Runtime |         Mean |       Error |      StdDev |       Median |          Min |          Max | Rank |  Gen 0 |  Gen 1 |  Gen 2 | Allocated |
--------------- |----- |-------- |-------------:|------------:|------------:|-------------:|-------------:|-------------:|-----:|-------:|-------:|-------:|----------:|
 CompletedAwait |  Clr |     Clr |    95.253 ns |   0.7491 ns |   0.6641 ns |    95.100 ns |    94.461 ns |    96.557 ns |    7 | 0.0075 |      - |      - |      24 B |
      Completed |  Clr |     Clr |    12.036 ns |   0.0659 ns |   0.0617 ns |    12.026 ns |    11.931 ns |    12.154 ns |    2 | 0.0076 |      - |      - |      24 B |
         Pragma |  Clr |     Clr |    87.868 ns |   0.3923 ns |   0.3670 ns |    87.789 ns |    87.336 ns |    88.683 ns |    6 | 0.0075 |      - |      - |      24 B |
     FromResult |  Clr |     Clr |   107.009 ns |   0.6671 ns |   0.6240 ns |   107.009 ns |   106.204 ns |   108.247 ns |    8 | 0.0584 |      - |      - |     184 B |
          Yield |  Clr |     Clr | 1,766.843 ns |  26.5216 ns |  24.8083 ns | 1,770.383 ns | 1,705.386 ns | 1,800.653 ns |    9 | 0.0877 | 0.0038 | 0.0019 |     320 B |
 CompletedAwait | Core |    Core |    37.201 ns |   0.1961 ns |   0.1739 ns |    37.227 ns |    36.970 ns |    37.559 ns |    4 | 0.0076 |      - |      - |      24 B |
      Completed | Core |    Core |     9.017 ns |   0.0690 ns |   0.0577 ns |     9.010 ns |     8.925 ns |     9.128 ns |    1 | 0.0076 |      - |      - |      24 B |
         Pragma | Core |    Core |    34.118 ns |   0.4576 ns |   0.4281 ns |    34.259 ns |    33.437 ns |    34.792 ns |    3 | 0.0076 |      - |      - |      24 B |
     FromResult | Core |    Core |    46.953 ns |   1.2728 ns |   1.1905 ns |    46.467 ns |    45.674 ns |    49.868 ns |    5 | 0.0533 |      - |      - |     168 B |
          Yield | Core |    Core | 2,480.980 ns | 199.4416 ns | 575.4347 ns | 2,291.978 ns | 1,810.644 ns | 4,085.196 ns |   10 | 0.0916 |      - |      - |     296 B |

দ্রষ্টব্য: FromResultসরাসরি তুলনা করা যায় না।

পরীক্ষার কোড:

   [RankColumn, MinColumn, MaxColumn, StdDevColumn, MedianColumn]
   [ClrJob, CoreJob]
   [HtmlExporter, MarkdownExporter]
   [MemoryDiagnoser]
 public class BenchmarkAsyncNotAwaitInterface
 {
string context = "text context";
[Benchmark]
public int CompletedAwait()
{
    var t = new CompletedAwaitTest();
    var a = t.DoAsync(context);
    a.Wait();
    return t.Length;
}

[Benchmark]
public int Completed()
{
    var t = new CompletedTest();
    var a = t.DoAsync(context);
    a.Wait();
    return t.Length;
}

[Benchmark]
public int Pragma()
{
    var t = new PragmaTest();
    var a = t.DoAsync(context);
    a.Wait();
    return t.Length;
}

[Benchmark]
public int Yield()
{
    var t = new YieldTest();
    var a = t.DoAsync(context);
    a.Wait();
    return t.Length;
}

    [Benchmark]
    public int FromResult()
    {
        var t = new FromResultTest();
        var t2 = t.DoAsync(context);
        return t2.Result;
    }

public interface ITestInterface
{
    int Length { get; }
    Task DoAsync(string context);
}

class CompletedAwaitTest : ITestInterface
{
    public int Length { get; private set; }
    public async Task DoAsync(string context)
    {
        Length = context.Length;
        await Task.CompletedTask;
    }
}

class CompletedTest : ITestInterface
{
    public int Length { get; private set; }
    public Task DoAsync(string context)
    {
        Length = context.Length;
        return Task.CompletedTask;
    }
}

class PragmaTest : ITestInterface
{
    public int Length { get; private set; }
    #pragma warning disable 1998
    public async Task DoAsync(string context)
    {
        Length = context.Length;
        return;
    }
    #pragma warning restore 1998
}

class YieldTest : ITestInterface
{
    public int Length { get; private set; }
    public async Task DoAsync(string context)
    {
        Length = context.Length;
        await Task.Yield();
    }
}

    public interface ITestInterface2
    {
        Task<int> DoAsync(string context);
    }

    class FromResultTest : ITestInterface2
    {
        public async Task<int> DoAsync(string context)
        {
            var i = context.Length;
            return await Task.FromResult(i);
        }
    }

}


1
এটি দুর্ভাগ্যজনক যে #pragmaএকটিকে মনে হয় যে ওভারহেড ব্যয় করে। সম্ভবত ঠিক যতটা ওভারহেড CompletedTaskআপনি ফিরে আসার পরিবর্তে একটি তৈরি এবং সম্পূর্ণ করেছেন AsyncOperation। সংকলকটি বলতে পেরে ভাল লাগবে যে পদ্ধতিটি যেভাবে কোনওভাবে সিঙ্ক্রোনালি চালিত হলে এড়িয়ে যাওয়া ঠিক হবে।
বিনকি

আপনি কীভাবে একইরকম অনুমান Task.CompletedTaskকরেন Task.FromResult? এটি জেনে রাখা আকর্ষণীয় হবে - আমি আশা করি যে ফ্রিআরসাল্টটি সাদৃশ্যপূর্ণ এবং তবুও যদি আপনাকে কোনও মান ফেরত দিতে হয় তবে সেরা অভিনয়শিল্পী হবেন।
ব্লুমোনকএমএন

আমি এটি যোগ করব। আমি মনে করি রাষ্ট্রের মেশিন কোড এই ক্ষেত্রে আরও ভারবস হবে এবং কমপ্লিটড টাস্ক জিতবে .দেখুন
রোমান পোকারভস্কিচ

1
নেট কোর ২.২ এর জন্য এই আপডেটটি দেখে ভাল লাগবে, যেহেতু অ্যাসিঙ্ক স্টেট মেশিনে বরাদ্দ ব্যাপকভাবে উন্নত করা হয়েছে
ত্রৈম

1
@ চেং আমি .NET কোর 2.2.0 এ মাপদণ্ড চালিয়েছি। স্পষ্টতই, বিভিন্ন হার্ডওয়ারের কারণে মোট সময় আলাদা হয় তবে অনুপাত মোটামুটি একই থাকে: পদ্ধতি | .NET Core 2.0.3 গড় | .NET কোর 2.2.0 মানে সমাপ্ত | 100% | 100% কমপ্লিটইয়েট | 412.57% | রেজাল্ট থেকে 377.22% | 520.72% | 590.89% প্রগমা | 378.37% | 346.64% ফলন | 27514.47% | 23602.38%
ঝড়

10

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

public async Task<object> test()
{
    throw await new AwaitableNotImplementedException<object>();
}

এটি সম্ভব করার জন্য আমি এখানে টাইপটি যুক্ত করেছি।

public class AwaitableNotImplementedException<TResult> : NotImplementedException
{
    public AwaitableNotImplementedException() { }

    public AwaitableNotImplementedException(string message) : base(message) { }

    // This method makes the constructor awaitable.
    public TaskAwaiter<AwaitableNotImplementedException<TResult>> GetAwaiter()
    {
        throw this;
    }
}

10

স্টিফেনের উত্তরের আপডেট হিসাবে, TaskConstantsনতুন সহায়ক সহায়ক পদ্ধতি হওয়ায় আপনাকে আর ক্লাসটি লেখার দরকার নেই :

    public Task ThrowException()
    {
        try
        {
            throw new NotImplementedException();
        }
        catch (Exception e)
        {
            return Task.FromException(e);
        }
    }

3
এটি করবেন না। স্ট্যাক ট্রেস আপনার কোডটি নির্দেশ করবে না। সম্পূর্ণরূপে আরম্ভ করার জন্য ব্যতিক্রম অবশ্যই ছুঁড়ে ফেলা উচিত।
ড্যানিয়েল বি

1
ড্যানিয়েল বি - হ্যাঁ, আপনি একেবারে ঠিক বলেছেন। ব্যতিক্রমটি সঠিকভাবে ছুঁড়ে ফেলার জন্য আমি আমার উত্তরটি পরিবর্তন করেছি।
ম্যাট

3

যদি আপনি ইতিমধ্যে প্রতিক্রিয়াশীল এক্সটেনশনের বিরুদ্ধে লিঙ্ক করেন তবে আপনি এটি করতেও পারেন:

public async Task<object> NotImplemented()
{
    await Observable.Throw(new NotImplementedException(), null as object).ToTask();
}

public async Task<object> SimpleResult()
{
    await Observable.Return(myvalue).ToTask();
}

প্রতিক্রিয়াশীল এবং অ্যাসিঙ্ক / প্রতীক্ষা উভয়ই নিজের মধ্যে এবং আশ্চর্যজনক, তবে তারা একসাথে খুব ভাল খেলে।

প্রয়োজনীয় অন্তর্ভুক্ত রয়েছে:

using System.Reactive.Linq;
using System.Reactive.Threading.Tasks;

3

এটি সিএস ১৯৯৮ এর নীচে ঘটতে পারে।

public async Task<object> Foo()
{
    return object;
}

তারপরে আপনি নীচে সংস্কার করতে পারেন।

public async Task<object> Foo()
{
    var result = await Task.Run(() =>
    {
        return object;
    });
    return result;
}



1

আপনার যদি অপেক্ষা করার কিছু না থাকে তবে টাস্কটি ফিরিয়ে দিন rom

public Task<int> Success() // note: no "async"
{
  ... // Do not have await code
  var result = ...;
  return Task.FromResult(result);
}

1

আপনার পদ্ধতির স্বাক্ষরের উপর নির্ভর করে এখানে কিছু বিকল্প রয়েছে।

    public async Task Test1()
    {
        await Task.CompletedTask;
    }

    public async Task<object> Test2()
    {
        return await Task.FromResult<object>(null);
    }

    public async Task<object> Test3()
    {
        return await Task.FromException<object>(new NotImplementedException());
    }

-1
// This is to get rid of warning CS1998, please remove when implementing this method.
await new Task(() => { }).ConfigureAwait(false);
throw new NotImplementedException();

-2

আপনি পদ্ধতি থেকে অ্যাসিঙ্ক কীওয়ার্ডটি ফেলে দিতে পারেন এবং কেবল এটি টাস্ক ফিরিয়ে দিতে পারেন;

    public async Task DoTask()
    {
        State = TaskStates.InProgress;
        await RunTimer();
    }

    public Task RunTimer()
    {
        return new Task(new Action(() =>
        {
            using (var t = new time.Timer(RequiredTime.Milliseconds))
            {
                t.Elapsed += ((x, y) => State = TaskStates.Completed);
                t.Start();
            }
        }));
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.