সমান্তরালভাবে দুটি এ্যাসিঙ্ক কাজ চালান এবং .NET 4.5 এ ফলাফল সংগ্রহ করুন


116

নেট .৪.৪ নিয়ে কাজ করা সহজ বলে আমি ভেবেছিলাম এমন কিছু পাওয়ার জন্য আমি কিছুক্ষণ চেষ্টা করছি

আমি একই সাথে দীর্ঘ দুটি চলমান কাজ বন্ধ করতে
এবং সেরা সি # 4.5 (আরটিএম) উপায়ে ফলাফল সংগ্রহ করতে চাই

নিম্নলিখিতটি কাজ করে তবে আমি এটি পছন্দ করি না কারণ:

  • আমি Sleepএকটি অ্যাসিঙ্ক পদ্ধতি হতে চাই যাতে এটি awaitঅন্যান্য পদ্ধতিগুলিও করতে পারে
  • এটি দেখতে কেবল আনাড়ি দেখায় Task.Run()
  • আমি মনে করি না যে এটি কোনও নতুন ভাষার বৈশিষ্ট্যগুলিও ব্যবহার করছে!

কাজের কোড:

public static void Go()
{
    Console.WriteLine("Starting");

    var task1 = Task.Run(() => Sleep(5000));    
    var task2 = Task.Run(() => Sleep(3000));

    int totalSlept = task1.Result + task2.Result;

    Console.WriteLine("Slept for a total of " + totalSlept + " ms");
}

private static int Sleep(int ms)
{
    Console.WriteLine("Sleeping for " + ms);
    Thread.Sleep(ms);
    Console.WriteLine("Sleeping for " + ms + " FINISHED");
    return ms;
}

অ-কার্যকারী কোড:

আপডেট: এটি আসলে কাজ করে এবং এটি করার সঠিক উপায়, একমাত্র সমস্যা Thread.Sleep

এই কোডটি কাজ করে না কারণ কলটি Sleep(5000)তাৎক্ষণিকভাবে টাস্কটি শুরু করে তাই Sleep(1000)এটি শেষ না হওয়া পর্যন্ত চলবে না। এই যদিও সত্য Sleepহয় asyncএবং আমি ব্যবহার করছি না awaitবা কলিং .Resultখুব শীঘ্রই।

আমি ভেবেছিলাম সম্ভবত Task<T>কোনও asyncপদ্ধতিতে কল করে অ-রান করার উপায় আছে যাতে আমি তখন Start()দুটি কাজ করতে পারি তবে আমি কীভাবে Task<T>একটি অ্যাসিঙ্ক পদ্ধতিটি কল করতে পারি তা বুঝতে পারি না ।

public static void Go()
{
    Console.WriteLine("Starting");

    var task1 = Sleep(5000);    // blocks
    var task2 = Sleep(1000);

    int totalSlept = task1.Result + task2.Result;

    Console.WriteLine("Slept for " + totalSlept + " ms");
}

private static async Task<int> Sleep(int ms)
{
    Console.WriteLine("Sleeping for " + ms);
    Thread.Sleep(ms);
    return ms;
}

দ্রষ্টব্য: Go
as

3
ব্লক task1.Resultনা ঘটছে ঘটছেvar task1 = Sleep(5000) কারণ অপেক্ষার কীওয়ার্ড ছাড়াই আপনার ঘুমের পদ্ধতিটি সিঙ্ক্রোনাস।
আরভিস

উত্তর:


86

আপনার async প্রোগ্রামিংয়ের জন্য ঘুমের পরিবর্তে Task.Delay ব্যবহার করা উচিত এবং তারপরে কার্য ফলাফলগুলি একত্রিত করতে Task.WhenAll ব্যবহার করা উচিত। কাজ সমান্তরাল চলবে।

public class Program
    {
        static void Main(string[] args)
        {
            Go();
        }
        public static void Go()
        {
            GoAsync();
            Console.ReadLine();
        }
        public static async void GoAsync()
        {

            Console.WriteLine("Starting");

            var task1 = Sleep(5000);
            var task2 = Sleep(3000);

            int[] result = await Task.WhenAll(task1, task2);

            Console.WriteLine("Slept for a total of " + result.Sum() + " ms");

        }

        private async static Task<int> Sleep(int ms)
        {
            Console.WriteLine("Sleeping for {0} at {1}", ms, Environment.TickCount);
            await Task.Delay(ms);
            Console.WriteLine("Sleeping for {0} finished at {1}", ms, Environment.TickCount);
            return ms;
        }
    }

11
এটি দুর্দান্ত উত্তর ... তবে আমি ভেবেছিলাম এই ভুলটি উত্তর না হওয়া পর্যন্ত আমি এটি চালিয়েছি। তাহলে আমি বুঝতে পেরেছি। এটি সত্যিই 5 সেকেন্ডের মধ্যে কার্যকর করে। কৌশলটি হ'ল কার্যগুলি তত্ক্ষণাত্ অপেক্ষা না করা, পরিবর্তে টাস্কের জন্য অপেক্ষা করুন hen
টিম লাভল-স্মিথ

113
async Task<int> LongTask1() { 
  ...
  return 0; 
}

async Task<int> LongTask2() { 
  ...
  return 1; 
}

...
{
   Task<int> t1 = LongTask1();
   Task<int> t2 = LongTask2();
   await Task.WhenAll(t1,t2);
   //now we have t1.Result and t2.Result
}

2
আমি +1 কারণ আপনি টি 1, টি 2 কে টাস্ক হিসাবে ঘোষণা করেন যা সঠিক উপায়।
মিনিম

12
আমি বিশ্বাস করি যে এই সমাধানটির জন্য গো পদ্ধতিটিও অ্যাসিঙ্ক হতে হবে, যার অর্থ এটি অ্যাসিঙ্ক্রোনাস হওয়ার ক্ষমতা প্রকাশ করে। যদি আপনি আরও কিছু জিজ্ঞাসাকারীর মতো করতে চান যেখানে কলারের Goপদ্ধতিটি সিঙ্ক্রোনাস হয় তবে দু'টি স্বতন্ত্র কাজ অবিচ্ছিন্নভাবে শেষ করতে চান (যেমন উভয়ের অপরের আগেই সম্পন্ন করার প্রয়োজন হয় না, তবে উভয়কে ফাঁসি কার্যকর হওয়ার আগেই সম্পন্ন Task.WaitAllকরতে হবে ) তবে আরও ভাল হবে, এবং আপনি ডান অপেক্ষার কীওয়ার্ডটির দরকার নেই, সুতরাং কলিং Goপদ্ধতিটি নিজেই অ্যাসিঙ্ক হওয়ার দরকার নেই। উভয়ই পদ্ধতির চেয়ে ভাল নয়, এটি আপনার লক্ষ্য কী তা কেবল বিষয়।
অ্যারোনএলএস

1
অকার্যকর async void LongTask1() {...}মিথোড : কোনও টাস্ক নেই es ফলাফল সম্পত্তি property যেমন ক্ষেত্রে টি ছাড়া কার্য ব্যবহার করুন: async Task LongTask1()
আরভিস

যে কোনও একটির কাজ থেকে আমি ফলাফল পাইনি। সুতরাং আমি এটিকে পরিবর্তন করেছি Task<TResult> t1 = LongTask1();এবং এখন পেয়েছি t1.Result<TResult>আপনার ফলাফলের ফিরে আসার ধরন। return <TResult>এটি কাজ করার জন্য আপনার পদ্ধতিতে একটি প্রয়োজন হবে ।
গিলু

1
এটি উল্লেখযোগ্য হতে পারে যে আপনি যদি কিছু সত্যই সাধারণ কাজ করে থাকেন এবং অতিরিক্ত t1এবং t2ভেরিয়েবলগুলি না চান তবে আপনি ব্যবহার করতে পারেন new Task(...)। উদাহরণস্বরূপ: int int1 = 0; await Task.WhenAll(new Task(async () => { int1 = await LongTask1(); }));। এই পদ্ধতির একটি ধরা হ'ল সংকলকটি বুঝতে পারবে না যে ভেরিয়েবলটি নির্ধারিত হয়েছিল এবং আপনি যদি এটির প্রাথমিক মান না দিয়ে থাকেন তবে এটিকে নিবন্ধিত হিসাবে গণ্য করবেন।
রবার্ট ডেনিস

3

যখন আপনার Sleepপদ্ধতিটি অ্যাসিঙ্ক,Thread.Sleep এটি নয়। অ্যাসিঙ্কের পুরো ধারণাটি হ'ল একক থ্রেড পুনরায় ব্যবহার করা, একাধিক থ্রেড শুরু করা নয়। আপনি থ্রেডে একটি সিঙ্ক্রোনাস কল ব্যবহার করে ব্লক করেছেন leep ঘুম, এটি কার্যকর হবে না।

আমি ধরে নিচ্ছি Thread.Sleep এটি আসলে আপনি যা করতে চান তার একটি সরলীকরণ। আপনার প্রকৃত বাস্তবায়নকে async পদ্ধতি হিসাবে কোড করা যেতে পারে?

আপনার যদি একাধিক সিঙ্ক্রোনাস ব্লকিং কল চালানোর দরকার হয় তবে অন্য কোথাও আমার মনে হয়!


ধন্যবাদ রিচার্ড - হ্যাঁ আমি যখন আমার সার্ভিস কলটি প্রকৃতপক্ষে ব্যবহার করি তখন প্রত্যাশার সাথে কাজ করা মনে হয়
সাইমন_উইভার

তাহলে অ্যাসিঙ্ক চালাবেন কীভাবে? আমি যে অ্যাপ্লিকেশনটি ফাইলের জন্য ফাইল সুইচিং এবং অপেক্ষা অনেক কাজ প্রায় 5 দ্বিতীয়, এবং তারপর অন্য প্রক্রিয়া আছে, যখন আমি "যখন জন্য সমস্ত" এটি প্রথম প্রথম, তারপর দ্বিতীয়, যদিও আমি বললাম সঞ্চালন করুন: var x = y(), এবং var x=await y()বা y().wait()এখনও এটি এখনো সমস্ত পথ অপেক্ষা করুন, এবং যদি অ্যাসিঙ্ক নিজে থেকে এটি পরিচালনা করে না, তবে আমার কী করা উচিত? নোট করুন যে y async দিয়ে সজ্জিত, এবং আমি আশা করি এটি সমস্ত ক্ষেত্রেই করা হবে, যেখানে এটি নির্ধারিত হয়েছে ঠিক সেখানে নয়, সম্পাদনা করুন: আমি যখন আমার সঙ্গীকে বলেছিলাম, আসুন চেষ্টা করি Task.Factory, এবং তিনি বলেছিলেন যে আমি যখন বিচ্ছিন্ন হয়েছি তখন এটি কাজ করেছে এই শ্রেণীর পক্ষ
মৃত মানব

2

এই বিষয়টির উত্তর দিতে:

আমি চাই ঘুম একটি অ্যাসিঙ্ক পদ্ধতি হোক যাতে এটি অন্যান্য পদ্ধতির জন্য অপেক্ষা করতে পারে

আপনি সম্ভবত Sleepফাংশনটি আবার লিখতে পারেন :

private static async Task<int> Sleep(int ms)
{
    Console.WriteLine("Sleeping for " + ms);
    var task = Task.Run(() => Thread.Sleep(ms));
    await task;
    Console.WriteLine("Sleeping for " + ms + "END");
    return ms;
}

static void Main(string[] args)
{
    Console.WriteLine("Starting");

    var task1 = Sleep(2000);
    var task2 = Sleep(1000);

    int totalSlept = task1.Result +task2.Result;

    Console.WriteLine("Slept for " + totalSlept + " ms");
    Console.ReadKey();
}

এই কোডটি চালনা করলে আউটপুট আসবে:

Starting
Sleeping for 2000
Sleeping for 1000
*(one second later)*
Sleeping for 1000END
*(one second later)*
Sleeping for 2000END
Slept for 3000 ms

2

এটা সপ্তাহান্তে এখন আছেন!

    public async void Go()
    {
        Console.WriteLine("Start fosterage...");

        var t1 = Sleep(5000, "Kevin");
        var t2 = Sleep(3000, "Jerry");
        var result = await Task.WhenAll(t1, t2);

        Console.WriteLine($"My precious spare time last for only {result.Max()}ms");
        Console.WriteLine("Press any key and take same beer...");
        Console.ReadKey();
    }

    private static async Task<int> Sleep(int ms, string name)
    {
            Console.WriteLine($"{name} going to sleep for {ms}ms :)");
            await Task.Delay(ms);
            Console.WriteLine("${name} waked up after {ms}ms :(";
            return ms;
    }

0

এই নিবন্ধটি অনেক কিছুই ব্যাখ্যা করতে সহায়তা করেছিল। এটি প্রায়শই জিজ্ঞাসিত স্টাইলে।

অ্যাসিঙ্ক / ওয়েভ এফএকিউ

এই অংশটি ব্যাখ্যা Thread.Sleepকরে যে একই মূল থ্রেডে কেন চালিত হয় - যা আমার প্রাথমিক বিভ্রান্তির দিকে নিয়ে যায়।

"Async" কীওয়ার্ডটি কি কোনও পদ্ধতির অনুরোধকে থ্রেডপুলের সাথে সারি করার জন্য সৃষ্টি করে? একটি নতুন থ্রেড তৈরি করতে? মঙ্গল গ্রহে রকেট জাহাজ চালু করতে?

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

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