যদি আমার ইন্টারফেসটিতে অবশ্যই টাস্কটি ফেরত যেতে হবে কোনও অপারেশন বাস্তবায়ন করার সর্বোত্তম উপায় কোনটি?


435

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

আমি Task.Delay(0)নীচে নিয়ে গিয়েছি , তবে আমি জানতে চাই যে ফাংশনটিকে অনেক বলা হয়ে থাকলে এর কোনও পারফরম্যান্স-পার্শ্ব-প্রতিক্রিয়া রয়েছে কিনা (যুক্তি দেখানোর জন্য, কয়েক সেকেন্ডে কয়েকবার বলুন):

  • এই সিনট্যাকটিক চিনির কি বড় কিছু হতে পারে?
  • এটি কি আমার অ্যাপ্লিকেশনটির থ্রেড পুলটি আটকে রাখতে শুরু করে?
  • সংকলক ছাড়পত্র কি Delay(0)আলাদাভাবে মোকাবেলা করার জন্য যথেষ্ট ?
  • চান return Task.Run(() => { });কোন আলাদা হতে?

একটি ভাল উপায় আছে কি?

using System.Threading.Tasks;

namespace MyAsyncTest
{
    internal interface IFooFace
    {
        Task WillBeLongRunningAsyncInTheMajorityOfImplementations();
    }

    /// <summary>
    /// An implementation, that unlike most cases, will not have a long-running
    /// operation in 'WillBeLongRunningAsyncInTheMajorityOfImplementations'
    /// </summary>
    internal class LazyBar : IFooFace
    {
        #region IFooFace Members

        public Task WillBeLongRunningAsyncInTheMajorityOfImplementations()
        {
            // First, do something really quick
            var x = 1;

            // Can't return 'null' here! Does 'Task.Delay(0)' have any performance considerations?
            // Is it a real no-op, or if I call this a lot, will it adversely affect the
            // underlying thread-pool? Better way?
            return Task.Delay(0);

            // Any different?
            // return Task.Run(() => { });

            // If my task returned something, I would do:
            // return Task.FromResult<int>(12345);
        }

        #endregion
    }

    internal class Program
    {
        private static void Main(string[] args)
        {
            Test();
        }

        private static async void Test()
        {
            IFooFace foo = FactoryCreate();
            await foo.WillBeLongRunningAsyncInTheMajorityOfImplementations();
            return;
        }

        private static IFooFace FactoryCreate()
        {
            return new LazyBar();
        }
    }
}

2
সংশ্লিষ্ট প্রশ্ন: stackoverflow.com/questions/4245968/create-a-completed-task
CodesInChaos

8
ব্যক্তিগতভাবে আমি সঙ্গে যেতে হবে Task.FromResult<object>(null)
কোডসইনচওস

উত্তর:


625

কোনও অপ-এক্সপ্রেশন দিয়ে একটি তৈরি করার চেয়ে কম ওভারহেড ব্যবহার করা হবে Task.FromResult(0)বা Task.FromResult<object>(null)হবে TaskTaskপ্রাক-নির্ধারিত ফলাফল সহ কোনও ফলাফল তৈরি করার সময়, কোনও সময়সূচী ওভারহেড জড়িত থাকে না।


আজ, আমি এটি সম্পাদন করতে Task.CompletedTask ব্যবহার করার পরামর্শ দেব ।


5
এবং যদি আপনি github.com/StephenCleary/AsyncEx ব্যবহার করছেন বলে মনে হয় তারা এই সম্পূর্ণ কাজগুলি আরও বেশ কয়েকটি কার্যকর উপায়ে সরবরাহ করার জন্য একটি টাস্ক কনস্ট্যান্টস ক্লাস সরবরাহ করে (0
আন্তঃ

5
return default(YourReturnType);
কিংবদন্তি

8
@ লেজেন্ডস যা সরাসরি কোনও টাস্ক তৈরি করার জন্য কাজ করে না
রিড কোপসি

18
আমি নিশ্চিত Task.CompletedTaskনা তবে কৌতুকটি করতে পারে! (তবে। নেট 4.6 প্রয়োজন)
পিটার

1
প্রশ্ন: এটি কীভাবে Task.FromResult<TResult>, যা একটি ফেরত দেয় Task<TResult>, তার ফেরতের প্রকারকে সন্তুষ্ট করেTask (কোনও প্রকারের প্যারাম নেই) ?
rory.ap

187

ব্যবহার সম্পর্কে রিড কোপসির উত্তরে যুক্ত করতে Task.FromResult, আপনি ইতিমধ্যে সম্পন্ন টাস্কের সমস্ত উদাহরণ একই হওয়ায় আপনি ইতিমধ্যে সম্পন্ন টাস্কটি ক্যাশে দিলে আপনি আরও কার্যকারিতা উন্নত করতে পারেন:

public static class TaskExtensions
{
    public static readonly Task CompletedTask = Task.FromResult(false);
}

সঙ্গে TaskExtensions.CompletedTaskআপনাকে সমগ্র অ্যাপ্লিকেশন ডোমেইন সর্বত্র একই উদাহরণস্বরূপ ব্যবহার করতে পারেন।


দ্য .NET Framework (v4.6) এর সর্বশেষ সংস্করণ যোগ করা শুধু যে সঙ্গে Task.CompletedTaskস্ট্যাটিক সম্পত্তি

Task completedTask = Task.CompletedTask;

আমার কি এটি ফিরিয়ে দেওয়ার বা তার অপেক্ষার দরকার আছে ?
পিক্সার

@ পিক্সার আপনার মানে কি? আপনি উভয়ই করতে পারেন, তবে এটির জন্য অপেক্ষা করা সিঙ্ক্রোনসিমে চলতে থাকবে।
i3arnon

দুঃখিত, আমার প্রসঙ্গটি উল্লেখ করতে হয়েছিল :) আমি এখন এটি দেখতে পাওয়ায়, আমরা public Task WillBeLongRunningAsyncInTheMajorityOfImplementations()পাশাপাশি তৈরি করতে পারি public async Task WillBeLongRunningAsyncInTheMajorityOfImplementations()। সুতরাং, আমরা হয় return CompletedTask;বা হয় await CompletedTask;। কী বেশি পছন্দনীয় (সম্ভবত আরও দক্ষ বা আরও একত্রিত)?
পিক্সার

3
@ পিক্সার আমি পরিষ্কার করতে চাই না। আমি "" নো-অ্যাসিঙ্ক "আরও দক্ষ হবে বলে বুঝিয়েছি। একটি পদ্ধতি async করা কম্পাইলারকে এটি একটি রাষ্ট্র-মেশিনে রূপান্তরিত করার নির্দেশ দেয়। এটি প্রতিবার আপনি যখন কল করবেন তখন এটি একটি নতুন কাজও তৈরি করবে। ইতিমধ্যে সম্পন্ন টাস্কটি ফিরিয়ে দেওয়া আরও পরিষ্কার এবং আরও পারফরম্যান্ট হবে।
i3arnon

3
@ আসাদ এটি বরাদ্দ হ্রাস করে (এবং এটির সাথে জিসি সময়ও)। নতুন মেমরি বরাদ্দ করার পরিবর্তে এবং আপনার যখন একটি সম্পূর্ণ টাস্ক প্রয়োজন তখন প্রতিবার একটি টাস্ক ইনস্ট্যান্ট তৈরি করার পরিবর্তে আপনি কেবল একবার এটি করেন।
i3arnon

38

Task.Delay(0)গৃহীত উত্তরের মতো এটি একটি ভাল পদ্ধতির ছিল, কারণ এটি একটি সম্পূর্ণরূপীর ক্যাশেড অনুলিপি Task

৪.6 হিসাবে এখন Task.CompletedTaskযা এর উদ্দেশ্যটিতে আরও স্পষ্ট, তবে কেবল Task.Delay(0)এখনও একটি একক ক্যাশেড উদাহরণ দেয় না, এটি একইরূপে ফিরে আসে মতো একক ক্যাশে উদাহরণস্বরূপ Task.CompletedTask

উভয়ের ক্যাশেড প্রকৃতিই স্থির থাকার গ্যারান্টিযুক্ত, তবে বাস্তবায়ন-নির্ভর অপটিমাইজেশন যা কেবলমাত্র বাস্তবায়ন-নির্ভরতা হিসাবে প্রত্যাশিত (যেমন, তারা এখনও কার্যকরভাবে কাজ করতে পারে যদি বাস্তবায়ন এমন কিছুতে পরিবর্তিত হয় যা এখনও বৈধ ছিল) এর ব্যবহার Task.Delay(0)ছিল গৃহীত উত্তরের চেয়ে ভাল।


1
আমি এখনও 4.5 ব্যবহার করছি এবং যখন আমি কিছু গবেষণা করেছিলাম তখন আমি জানতে পেরে আনন্দিত হয়েছি যে টাস্ক.ডেলি (0) একটি স্ট্যাটিক কমপ্লিটড টাস্ক সদস্যকে ফিরিয়ে আনার জন্য বিশেষ কেসযুক্ত। যা আমি তখন নিজের স্ট্যাটিক কমপ্লিটড টাস্ক মেম্বারে ক্যাশে করেছিলাম। : পি
ড্যারেন ক্লার্ক

2
আমি জানি না, তবে Task.CompletedTaskপিসিএল প্রকল্পে ব্যবহার করা যাবে না, যদিও আমি .net সংস্করণটি 4.6 (প্রোফাইল 7) এ সরিয়ে রেখেছি, কেবলমাত্র ভিএস2017 তে পরীক্ষা করা হয়েছে।
ফেলিক্স

@ ফাই আমি অনুমান করেছিলাম এটি অবশ্যই পিসিএল এপিআই পৃষ্ঠের অংশ না হওয়া উচিত, যদিও পিসিএল সমর্থন করে এই মুহুর্তে একমাত্র কাজটিও 4.5 সমর্থন করে তাই আমি ইতিমধ্যে এটি Task.CompletedTask => Task.Delay(0);সমর্থন করার জন্য আমার নিজের ব্যবহার করতে চলেছি , তাই আমি ডোন না আমার মাথার উপরের অংশটি নিশ্চিতভাবে জানতে পারছি না।
জন হান্না

17

সম্প্রতি এটির মুখোমুখি হয়েছি এবং পদ্ধতিটি বাতিল হওয়া সম্পর্কে সতর্কতা / ত্রুটিগুলি পেয়ে চলেছে।

আমরা সংকলকটি বসানোর ব্যবসায় করছি এবং এটি এটি পরিষ্কার করে দেয়:

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

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


17
এটা সম্পূর্ণ ভুল। আপনি একটি সংকলক ত্রুটি পেয়ে যাচ্ছেন কারণ পদ্ধতির সংজ্ঞাটিতে এসিংক রয়েছে, তাই সংকলকটি অপেক্ষা করার প্রত্যাশা করে। "সঠিক" ব্যবহারটি পাবলিক টাস্ক মাইভয়েডএন্সিঙ্কমেথোগ () হবে {রিটার্ন টাস্ক Com কমপ্লিটড টাস্ক;}
কিথ

3
এটিকে কেন সবচেয়ে
শুদ্ধ

3
কিথের মন্তব্যের কারণে।
নোকেলাস

4
তিনি সম্পূর্ণ ভুল নন, তিনি সবেমাত্র অ্যাসিঙ্ক কীওয়ার্ডটি সরিয়ে দিয়েছেন। আমার পন্থা আরও মূর্খ। তাঁর নগণ্য। কিছুটা অভদ্র না হলে।
আলেকজান্ডার ট্রুজি

1
এটি কোনও অর্থবোধ করে না, এখানে কীথের সাথে সম্পূর্ণ একমত, আমি আসলে সমস্ত উত্স পাই না। আপনি প্রয়োজনীয় কোডটি কেন যুক্ত করবেন? public Task MyVoidAsyncMethod() {}সম্পূর্ণরূপে উপরের পদ্ধতির মতোই। এটির মতো ব্যবহারের জন্য যদি কোনও ইউসকেস থাকে তবে দয়া করে অতিরিক্ত কোড যুক্ত করুন।
নিক এন।


9

যখন আপনাকে অবশ্যই নির্দিষ্ট প্রকারটি ফিরে আসতে হবে:

Task.FromResult<MyClass>(null);

3

আমি Task completedTask = Task.CompletedTask;নেট 4.6 এর সমাধানটিকে অগ্রাধিকার দিই , তবে অন্য পদ্ধতিটি হ'ল পদ্ধতিটিকে অ্যাসিঙ্ক হিসাবে চিহ্নিত করে বাতিল করে দেওয়া:

    public async Task WillBeLongRunningAsyncInTheMajorityOfImplementations()
    {
    }

আপনি একটি সতর্কতা পাবেন (CS1998 - প্রত্যাশার অভিব্যক্তি ছাড়াই অ্যাসিঙ্ক ফাংশন), তবে এটি এই প্রসঙ্গে উপেক্ষা করা নিরাপদ।


1
যদি আপনার পদ্ধতিটি অকার্যকর ফিরে আসে তবে আপনার ব্যতিক্রম নিয়ে সমস্যা থাকতে পারে।
অ্যাডাম টিউলিপার - এমএসএফটি

0

আপনি যদি জেনেরিক ব্যবহার করছেন তবে সমস্ত উত্তর আমাদের সংকলন ত্রুটি দেবে। আপনি ব্যবহার করতে পারেন return default(T);। আরও ব্যাখ্যা করতে নীচের নমুনা।

public async Task<T> GetItemAsync<T>(string id)
            {
                try
                {
                    var response = await this._container.ReadItemAsync<T>(id, new PartitionKey(id));
                    return response.Resource;
                }
                catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
                {

                    return default(T);
                }

            }

ডাউনটা কেন?
কার্তিকেইকন ভি কে

প্রশ্ন ASYNC পদ্ধতিগুলির :) ছিল না
Frode Nilsen

0
return await Task.FromResult(new MyClass());

3
এই কোডটি কীভাবে এবং কেন এই সমস্যার সমাধান করে তার ব্যাখ্যা সহ প্রশ্নটি সমাধান করতে পারে যদিও আপনার পোস্টের মান উন্নত করতে সত্যই সহায়তা করবে এবং সম্ভবত আরও বেশি ভোটের ফলাফল হবে। মনে রাখবেন যে আপনি ভবিষ্যতে পাঠকদের জন্য প্রশ্নের উত্তর দিচ্ছেন, কেবল এখনই জিজ্ঞাসা করা ব্যক্তি নয়। দয়া করে সম্পাদনা ব্যাখ্যা যোগ করতে পারেন এবং সীমাবদ্ধতা এবং অনুমানের কি প্রয়োগ একটি ইঙ্গিত দিতে আপনার উত্তর।
ডেভিড বাক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.