কনসোল অ্যাপ্লিকেশনের 'মেইন' পদ্ধতিতে 'অ্যাসিঙ্ক' পরিবর্তনকারী নির্দিষ্ট করতে পারে না


445

আমি asyncসংশোধক সহ অ্যাসিক্রোনাস প্রোগ্রামিংয়ে নতুন । আমি কীভাবে Mainকনসোল অ্যাপ্লিকেশন পদ্ধতিটি অ্যাসিঙ্ক্রোনালি চালিত হয় তা নিশ্চিত করার জন্য আমি চেষ্টা করার চেষ্টা করছি ।

class Program
{
    static void Main(string[] args)
    {
        Bootstrapper bs = new Bootstrapper();
        var list = bs.GetList();
    }
}

public class Bootstrapper {

    public async Task<List<TvChannel>> GetList()
    {
        GetPrograms pro = new GetPrograms();

        return await pro.DownloadTvChannels();
    }
}

আমি জানি এটি "শীর্ষ" থেকে অবিচ্ছিন্নভাবে চলছে না। যেহেতু পদ্ধতিতে asyncসংশোধক নির্দিষ্ট করা সম্ভব নয় Main, তাই আমি কীভাবে mainসংযোজনীয়ভাবে কোড চালাতে পারি ?


23
এটি আর সি # 7.1-তে কেস হয় না। প্রধান পদ্ধতিগুলি
অ্যাসিঙ্ক

2
এখানে সি # 7.1 ব্লগ পোস্টের ঘোষণাঅ্যাসিঙ্ক মেইন শিরোনামে বিভাগটি দেখুন ।
স্টাইফলে

উত্তর:


382

যেমনটি আপনি আবিষ্কার করেছেন, ভিএস 11-এ সংকলকটি কোনও async Mainপদ্ধতিকে অস্বীকার করবে । এটি এসিএনসি সিটিপি সহ ভিএস 2010 এ অনুমোদিত (তবে কখনও প্রস্তাবিত হয়নি)।

অ্যাসিঙ্ক / প্রতীক্ষা এবং বিশেষত অ্যাসিঙ্ক্রোনাস কনসোল প্রোগ্রাম সম্পর্কে আমার সাম্প্রতিক ব্লগ পোস্ট রয়েছে । ইন্ট্রো পোস্ট থেকে কিছু পটভূমি তথ্য এখানে:

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

পরবর্তী সময়ে, যখন প্রতীক্ষিতটি সম্পূর্ণ হয়, এটি অ্যাসিঙ্ক পদ্ধতির বাকী অংশটি নির্ধারিত করবে (ধরা পড়া প্রসঙ্গে)।

কনসোল প্রোগ্রামগুলিতে এটি সহ একটি সমস্যা কেন তা এখানে রয়েছে async Main:

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

একটি সমাধান হ'ল আপনার নিজস্ব প্রসঙ্গ সরবরাহ করা - আপনার কনসোল প্রোগ্রামের জন্য একটি "প্রধান লুপ" যা অ্যাসিঙ্ক-সামঞ্জস্যপূর্ণ।

আপনার যদি অ্যাসিঙ্ক সিটিপি সহ কোনও মেশিন থাকে তবে আপনি আমার ডকুমেন্টস \ মাইক্রোসফ্ট ভিজ্যুয়াল স্টুডিও অ্যাসিঙ্ক সিটিপি \ নমুনা (সি # টেস্টিং) ইউনিট টেস্টিং \ অ্যাসিঙ্কটেষ্ট ইউটিলিটিগুলিGeneralThreadAffineContext থেকে ব্যবহার করতে পারেন । বিকল্পভাবে, আপনি আমার নিতো.অ্যাক্সেক্স এক্স নিউগেট প্যাকেজটি থেকে ব্যবহার করতে পারেন ।AsyncContext

এখানে ব্যবহার করে একটি উদাহরণ দেওয়া হয়েছে AsyncContext; GeneralThreadAffineContextপ্রায় অভিন্ন ব্যবহার আছে:

using Nito.AsyncEx;
class Program
{
    static void Main(string[] args)
    {
        AsyncContext.Run(() => MainAsync(args));
    }

    static async void MainAsync(string[] args)
    {
        Bootstrapper bs = new Bootstrapper();
        var list = await bs.GetList();
    }
}

বিকল্পভাবে, আপনার অ্যাসিক্রোনাস কাজ শেষ না হওয়া পর্যন্ত আপনি কেবলমাত্র মূল কনসোল থ্রেডটি ব্লক করতে পারেন:

class Program
{
    static void Main(string[] args)
    {
        MainAsync(args).GetAwaiter().GetResult();
    }

    static async Task MainAsync(string[] args)
    {
        Bootstrapper bs = new Bootstrapper();
        var list = await bs.GetList();
    }
}

এর ব্যবহারটি নোট করুন GetAwaiter().GetResult(); এটি AggregateExceptionযদি আপনি ব্যবহার করেন Wait()বা করেন তবে মোড়ক এড়ানো যায় Result

আপডেট, 2017-11-30: ভিজ্যুয়াল স্টুডিও 2017 আপডেট 3 (15.3) হিসাবে, ভাষা এখন একটি সমর্থন করে async Main- যতক্ষণ না এটি ফিরে আসে Taskবা আসে Task<T>। সুতরাং আপনি এখন এটি করতে পারেন:

class Program
{
    static async Task Main(string[] args)
    {
        Bootstrapper bs = new Bootstrapper();
        var list = await bs.GetList();
    }
}

শব্দার্থকগুলি GetAwaiter().GetResult()মূল থ্রেডটি ব্লক করার শৈলীর মতো দেখা যায় । তবে, সি # 7.1 এর জন্য এখনও কোনও ভাষার অনুমান নেই, সুতরাং এটি কেবলমাত্র অনুমান।


30
আপনি একটি সাধারণ বা ব্যবহার করতে পারেন এবং এতে কোনও ভুল নেই। তবে সচেতন থাকুন যে দুটি গুরুত্বপূর্ণ পার্থক্য রয়েছে: 1) সমস্ত ধারাবাহিকতা মূল থ্রেডের চেয়ে থ্রেড পুলে চালিত হয় এবং 2) কোনও ব্যতিক্রম একটিতে আবৃত থাকে । WaitResultasyncAggregateException
স্টিফেন ক্লিয়ারি

2
এটি (এবং আপনার ব্লগ পোস্ট) না হওয়া অবধি এটি নির্ণয় করতে আসলেই সমস্যা ছিল। এই সমস্যাটি সমাধানের এটি এখন পর্যন্ত সবচেয়ে সহজ পদ্ধতি এবং আপনি কেবলমাত্র "ইনস্টল-প্যাকেজ নিতো.এেন্সেন্সেক্স" দিয়ে নুগেট কনসোলে প্যাকেজটি ইনস্টল করতে পারেন এবং আপনার কাজ শেষ হয়েছে।
কনস্টান্টাইনেকে

1
@ স্টেফেন ক্লিয়ারি: দ্রুত সাড়া দেওয়ার জন্য ধন্যবাদ স্টিফেন। আমি বুঝতে পারি না যে কোনও ব্যতিক্রম ছোঁড়া হলে কেন কেউ ডিবাগারটি ভেঙে ফেলতে চান না । যদি আমি ডিবাগ করছি এবং কোনও নাল রেফারেন্স ব্যতিক্রম জুড়ে চলেছি তবে কোডের আপত্তিকর লাইনে সরাসরি যাওয়া পছন্দসই বলে মনে হচ্ছে। ভিএস সিঙ্ক্রোনাস কোডের জন্য "বাক্সের বাইরে" এর মতো কাজ করে, তবে অ্যাসিঙ্ক / প্রতীক্ষার জন্য নয়।
গ্রেগ

6
সি # 7.1 এর এখন একটি অ্যাসিঙ্ক মেইন রয়েছে
এসএসআরপ্লাং

3
আপনি যদি ভিএস 2017-তে সি # 7.1 সংস্করণ ব্যবহার করেন তবে আমার নিশ্চিত হওয়া দরকার যে এখানে প্রকল্পটি <LangVersion>latest</LangVersion>সিএসপোজ ফাইলটিতে যুক্ত করে ভাষার সর্বশেষতম সংস্করণটি ব্যবহার করার জন্য কনফিগার করা হয়েছে
লিয়াম

359

আপনি এই সাধারণ নির্মাণ দিয়ে এটি সমাধান করতে পারেন:

class Program
{
    static void Main(string[] args)
    {
        Task.Run(async () =>
        {
            // Do any async anything you need here without worry
        }).GetAwaiter().GetResult();
    }
}

এটি থ্রেডপুলের যেখানে আপনি এটি করতে চান সেখানে সবকিছুই ফেলে দেবে (সুতরাং অন্যান্য কাজগুলি আপনি শুরু / অপেক্ষায় থাকা কোনও থ্রেডে পুনরায় যোগদানের চেষ্টা করবেন না) এবং কনসোল অ্যাপ্লিকেশনটি বন্ধ করার আগে সবকিছু শেষ না হওয়া পর্যন্ত অপেক্ষা করুন। বিশেষ লুপ বা বাইরের লিবের প্রয়োজন নেই।

সম্পাদনা করুন: অবিচ্ছিন্ন ব্যতিক্রমগুলির জন্য অ্যান্ড্রুয়ের সমাধান অন্তর্ভুক্ত করুন।


3
এই পদ্ধতিটি খুব সুস্পষ্ট তবে ব্যতিক্রমগুলি মোড়ানোর প্রবণতা রয়েছে তাই আমি এখন আরও একটি ভাল উপায়ের জন্য খুঁজছি।
abatishchev

2
@ আবাতিষেভ আপনার কোডটি চেষ্টা করে / ধরার চেষ্টা করা উচিত, কমপক্ষে টাস্কের ভিতরে। ব্যর্থ হতে পারে এমন জিনিসগুলির চারপাশে চেষ্টা / ধরার মাধ্যমে আপনি মোড়ানো সমস্যা এড়াতে পারবেন।
ক্রিস মোসচিনি

54
যদি আপনি এটি প্রতিস্থাপন Wait()করেন GetAwaiter().GetResult()তবে AggregateExceptionজিনিসগুলি নিক্ষেপ করার সময় আপনি মোড়ক এড়াতে পারবেন ।
অ্যান্ড্রু আর্নট

7
এই হল কিভাবে async mainসি শার্প 7.1 চালু করা হচ্ছে, এই লেখার হিসাবে।
ব্যবহারকারী 9993

@ user9993 এই প্রস্তাব অনুসারে , এটি ঠিক সত্য নয়।
সিনজাই

90

আপনি নিম্নলিখিত কাজগুলি করে বাহ্যিক গ্রন্থাগারগুলির প্রয়োজন ছাড়াই এটি করতে পারেন:

class Program
{
    static void Main(string[] args)
    {
        Bootstrapper bs = new Bootstrapper();
        var getListTask = bs.GetList(); // returns the Task<List<TvChannel>>

        Task.WaitAll(getListTask); // block while the task completes

        var list = getListTask.Result;
    }
}

7
মনে রাখবেন যে getListTask.Resultএটিও একটি ব্লকিং কল এবং সুতরাং উপরের কোডটি ছাড়া লেখা যেতে পারে Task.WaitAll(getListTask)
do0g

27
এছাড়াও, যদি GetListছুড়ে AggregateExceptionফেলা হয় তবে নিক্ষেপ করা আসল ব্যতিক্রম নির্ধারণ করতে আপনাকে এটি ধরতে হবে এবং এর ব্যতিক্রমগুলি জিজ্ঞাসাবাদ করতে হবে। তবে, কল করতে পারেন GetAwaiter()পেতে TaskAwaiterজন্য Task, এবং কল GetResult(), সেটিতে অর্থাত var list = getListTask.GetAwaiter().GetResult();TaskAwaiter(এছাড়াও একটি ব্লকিং কল) থেকে ফলাফল পাওয়ার সময় নিক্ষিপ্ত কোনও ব্যতিক্রম একটিতে আবৃত হবে না AggregateException
do0g

1
.GetAwaiter ()। GetResult ছিল আমার উত্তরটি। আমি যা করার চেষ্টা করেছিলাম তার জন্য এটি পুরোপুরি কাজ করে। আমি সম্ভবত এটি অন্য জায়গায়ও ব্যবহার করব।
ডেথস্টালকার

78

সি # 7.1 এ আপনি একটি উপযুক্ত অ্যাসিঙ্ক মেইন করতে সক্ষম হবেন । Mainপদ্ধতির জন্য উপযুক্ত স্বাক্ষরগুলি প্রসারিত হয়েছে:

public static Task Main();
public static Task<int> Main();
public static Task Main(string[] args);
public static Task<int> Main(string[] args);

যেমন আপনি করছেন:

static async Task Main(string[] args)
{
    Bootstrapper bs = new Bootstrapper();
    var list = await bs.GetList();
}

সংকলনের সময়, অ্যাসিঙ্ক এন্ট্রি পয়েন্ট পদ্ধতিটি কল করার জন্য অনুবাদ করা হবে GetAwaitor().GetResult()

বিশদ: https://blogs.msdn.microsoft.com/mazhou/2017/05/30/c-7-series-part-2-async-main

সম্পাদনা করুন:

সি # 7.1 ভাষার বৈশিষ্ট্যগুলি সক্ষম করতে, আপনাকে প্রকল্পের ডান ক্লিক করতে হবে এবং "সম্পত্তি" ক্লিক করতে হবে তারপরে "বিল্ড" ট্যাবে যেতে হবে। সেখানে, নীচে উন্নত বোতামটি ক্লিক করুন:

এখানে চিত্র বর্ণনা লিখুন

ভাষার সংস্করণ ড্রপ-ডাউন মেনু থেকে, "7.1" (বা কোনও উচ্চতর মান) নির্বাচন করুন:

এখানে চিত্র বর্ণনা লিখুন

ডিফল্টটি হ'ল সর্বশেষ প্রধান সংস্করণ "যা মূল্যায়ন করবে (এই লেখার সময়) সি # 7.0 তে, যা কনসোল অ্যাপ্লিকেশনগুলিতে অ্যাসিঙ্ক মেনকে সমর্থন করে না।


2
এফডব্লিউআইডাব্লু এটি ভিজ্যুয়াল স্টুডিও 15.3 এবং তার বেশি পাওয়া যায় যা বর্তমানে এটি একটি বিটা / পূর্বরূপ প্রকাশ হিসাবে উপলব্ধ: ভিজ্যুয়ালস্টুডিও
মাহমুদ আল-কুদসি

এক মিনিট অপেক্ষা করুন ... আমি একটি সম্পূর্ণ আপডেট ইনস্টল চালাচ্ছি এবং আমার সর্বশেষ বিকল্পটি 7.1 ... আপনি কীভাবে ইতিমধ্যে মে মাসে 7.2 পেতে পারেন?

উত্তর আমার ছিল। অক্টোবর সম্পাদনাটি তখন অন্য কারও দ্বারা হয়েছিল যখন আমি মনে করি 7.2 (পূর্বরূপ?) প্রকাশিত হতে পারে।
নওফাল

1
শীর্ষস্থানীয় - আপনি যখন এটি করবেন ঠিক তখনই এটি ডিবাগ নয়, সমস্ত কনফিগারে রয়েছে কিনা তা পরীক্ষা করুন!
user230910

1
@ ব্যবহারকারী 230910 ধন্যবাদ। সি # টিমের একটি অদ্ভুত পছন্দ।
নওফাল

74

আমি একটি গুরুত্বপূর্ণ বৈশিষ্ট্য যুক্ত করব যা অন্যান্য উত্তরগুলির সমস্তই অগ্রাহ্য করেছে: বাতিলকরণ।

টিপিএলের একটি বড় বিষয় বাতিল সমর্থন, এবং কনসোল অ্যাপ্লিকেশনগুলিতে (সিটিআরএল + সি) অন্তর্নিহিত বাতিল করার একটি পদ্ধতি রয়েছে। তাদের একসাথে আবদ্ধ করা খুব সহজ। আমি আমার সমস্ত অ্যাসিঙ্ক কনসোল অ্যাপ্লিকেশনকে এভাবেই গঠন করি:

static void Main(string[] args)
{
    CancellationTokenSource cts = new CancellationTokenSource();

    System.Console.CancelKeyPress += (s, e) =>
    {
        e.Cancel = true;
        cts.Cancel();
    };

    MainAsync(args, cts.Token).Wait();
}

static async Task MainAsync(string[] args, CancellationToken token)
{
    ...
}

বাতিলকরণ টোকেনটিও কি পাস করা উচিত Wait()?
দর্শকরা

5
না, কারণ আপনি চান যে অ্যাসিঙ্ক কোডটি রহস্যজনকভাবে বাতিলকরণ পরিচালনা করতে সক্ষম হবে। আপনি যদি এটিকে পাস করেন তবে Wait()এটি অ্যাসিঙ্ক কোডটি শেষ হওয়ার জন্য অপেক্ষা করবে না - এটি অপেক্ষা করা বন্ধ করবে এবং অবিলম্বে প্রক্রিয়াটি শেষ করবে।
কোরি নেলসন

আপনি কি এ ব্যাপারে নিশ্চিত? আমি কেবল এটি ব্যবহার করে দেখেছি এবং মনে হচ্ছে বাতিল করার অনুরোধটি গভীর স্তরে প্রক্রিয়া করা হচ্ছে, এমনকি Wait()পদ্ধতিটি একই টোকেনটি পাস করার পরেও । আমি যা বলার চেষ্টা করছি তা হ'ল এটি কোনও তাত্পর্যপূর্ণ বলে মনে হচ্ছে না।
দর্শক

4
আমি নিশ্চিত. আপনি অপটিকে নিজেই বাতিল করতে চান, অপের সমাপ্তির অপেক্ষার জন্য নয়। ক্লিনআপ কোড ফিনিশিং বা এর ফলাফল সম্পর্কে আপনি যদি চিন্তা না করেন তবে।
কোরি নেলসন 21

1
হ্যাঁ, আমি মনে করি আমি এটি পেয়েছি, এটি আমার কোডে কোনও পার্থক্য করেছে বলে মনে হচ্ছে না। আর একটি বিষয় যা আমাকে অবশ্যই বাতিল করে দিয়েছিল ওয়েট পদ্ধতির বাতিলকরণকে সমর্থন করার বিষয়ে একটি নম্র রিশার্পার ইঙ্গিত ছিল;) আপনি উদাহরণটিতে একটি চেষ্টা করার বিষয়টিকে অন্তর্ভুক্ত করতে চাইতে পারেন, কারণ এটি একটি অপারেশন
ক্যান্সেলড এক্সসেপশন

22

সি # 7.1 (বনাম 2017 আপডেট 3 ব্যবহার করে) অ্যাসিঙ্ক প্রধানটির সাথে পরিচয় করিয়ে দেয়

তুমি লিখতে পারো:

   static async Task Main(string[] args)
  {
    await ...
  }

আরও তথ্যের জন্য সি # 7 সিরিজ, পর্ব 2: অ্যাসিঙ্ক মেইন

হালনাগাদ:

আপনি একটি সংকলন ত্রুটি পেতে পারেন:

প্রোগ্রামে কোনও এন্ট্রি পয়েন্টের জন্য উপযুক্ত একটি স্থিতিশীল 'মেইন' পদ্ধতি থাকে না

এই ত্রুটিটি কারণ vs2017.3 সি # 7.0 হিসাবে সি # 7.1 নয় ডিফল্টরূপে কনফিগার করা হয়েছে।

আপনার প্রকল্পের সি # 7.1 বৈশিষ্ট্যগুলি স্পষ্ট করে সংশোধন করা উচিত।

আপনি দুটি পদ্ধতি দ্বারা সি # 7.1 সেট করতে পারেন:

পদ্ধতি 1: প্রকল্প সেটিংস উইন্ডো ব্যবহার করে:

  • আপনার প্রকল্পের সেটিংস খুলুন
  • বিল্ড ট্যাবটি নির্বাচন করুন
  • উন্নত বোতামটি ক্লিক করুন
  • নিম্নলিখিত চিত্রটিতে প্রদর্শিত হিসাবে আপনি চান সংস্করণটি নির্বাচন করুন:

এখানে চিত্র বর্ণনা লিখুন

পদ্ধতি 2: ম্যানুয়ালি .csproj এর প্রপার্টি গ্রুপটি পরিবর্তন করুন

এই সম্পত্তি যুক্ত করুন:

    <LangVersion>7.1</LangVersion>

উদাহরণ:

    <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
        <PlatformTarget>AnyCPU</PlatformTarget>
        <DebugSymbols>true</DebugSymbols>
        <DebugType>full</DebugType>
        <Optimize>false</Optimize>
        <OutputPath>bin\Debug\</OutputPath>
        <DefineConstants>DEBUG;TRACE</DefineConstants>
        <ErrorReport>prompt</ErrorReport>
        <WarningLevel>4</WarningLevel>
        <Prefer32Bit>false</Prefer32Bit>
        <LangVersion>7.1</LangVersion>
    </PropertyGroup>    

20

আপনি C # এর 7.1 বা ব্যবহার পরে থাকেন, তবে সঙ্গে যেতে nawfal এর উত্তর এবং মাত্র আপনার প্রধান পদ্ধতির রিটার্ন টাইপ পরিবর্তন Taskবা Task<int>। আপনি যদি না হন:

  • async Task MainAsync জোহান বলেছিলেন মত একটি আছে ।
  • ডঃ জি-এর মত.GetAwaiter().GetResult() অন্তর্নিহিত ব্যতিক্রম ধরতে কল করুন said
  • সমর্থন বাতিল হিসাবে Cory ড
  • একটি সেকেন্ডের সাথে CTRL+Cসাথে প্রক্রিয়াটি শেষ করা উচিত। (ধন্যবাদ বিনকি !)
  • হ্যান্ডেল OperationCancelledException- একটি উপযুক্ত ত্রুটি কোড ফিরে।

চূড়ান্ত কোডটি দেখে মনে হচ্ছে:

private static int Main(string[] args)
{
    var cts = new CancellationTokenSource();
    Console.CancelKeyPress += (s, e) =>
    {
        e.Cancel = !cts.IsCancellationRequested;
        cts.Cancel();
    };

    try
    {
        return MainAsync(args, cts.Token).GetAwaiter().GetResult();
    }
    catch (OperationCanceledException)
    {
        return 1223; // Cancelled.
    }
}

private static async Task<int> MainAsync(string[] args, CancellationToken cancellationToken)
{
    // Your code...

    return await Task.FromResult(0); // Success.
}

1
অনেকগুলি দুর্দান্ত প্রোগ্রাম কেবল ক্যান্সেলকিপ্রেসকে কেবল প্রথমবারেই বাতিল করে দেবে যাতে আপনি একবার ^ সি চাপলে একবার আপনি কৃপণভাবে শাটডাউন পান তবে আপনি অধৈর্য হয়ে থাকলে দ্বিতীয় ^ সে সি বাতিল হয়ে যায়। এই সমাধানের সাথে, আপনাকে প্রোগ্রামটি ম্যানুয়ালি মেরে ফেলতে হবে যদি এটি e.Cancel = trueশর্তবিহীন কারণ বাতিলকরণ টোকেনকে সম্মান জানাতে ব্যর্থ হয় ।
বিনকি 1'18

19

এখনও এর খুব বেশি প্রয়োজন নেই, তবে আমি যখন দ্রুত পরীক্ষার জন্য কনসোল অ্যাপ্লিকেশন ব্যবহার করেছি এবং অ্যাসিঙ্কের প্রয়োজনীয়তা পেয়েছি তখন আমি ঠিক এটির মতো সমাধান করেছি:

class Program
{
    static void Main(string[] args)
    {
        MainAsync(args).Wait();
    }

    static async Task MainAsync(string[] args)
    {
        // Code here
    }
}

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

6
সত্য নয়, @ মনুশিনআইগোর। কমপক্ষে এই তুচ্ছ উদাহরণটিতে SynchronizationContextমূল থ্রেডের সাথে কোনও সম্পর্ক নেই । সুতরাং এটি অচলাবস্থার কারণ না ছাড়াও ConfigureAwait(false)সমস্ত ধারাবাহিকতা থ্রেডপুলে কার্যকর হবে।
অ্যান্ড্রু আর্নট

7

মেইন থেকে অ্যাসিঙ্ক্রোনালি কল টাস্কের জন্য, ব্যবহার করুন

  1. .NET 4.5 এর জন্য Task.Run ()

  2. নেট নেট 4.0.০ এর জন্য টাস্ক.ফ্যাক্টরি.স্টার্টনিউ () অ্যাসিঙ্কের জন্য মাইক্রোসফ্ট.বিসিএল.এসিঙ্ক লাইব্রেরির প্রয়োজন হতে পারে এবং কীওয়ার্ডের জন্য অপেক্ষা করতে পারে)

বিশদ: http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx


4

মূলত কলটি getList এ পরিবর্তন করার চেষ্টা করুন:

Task.Run(() => bs.GetList());

4

যখন সি # 5 সিটিপি চালু হয়েছিল, আপনি অবশ্যই মেইনটিকে অবশ্যই চিহ্নিত করতে পারেনasync ... যদিও এটি করা ভাল ধারণা ছিল না। আমি বিশ্বাস করি এটি একটি ত্রুটি হয়ে ওঠার জন্য ভিএস 2013 প্রকাশের মাধ্যমে পরিবর্তিত হয়েছিল।

আপনি যদি অন্য কোনও অগ্রভাগ থ্রেড Mainশুরু না করেন তবে কিছু প্রোগ্রাম ব্যাকগ্রাউন্ডের কাজ শুরু করা হলেও আপনার প্রোগ্রামটি সম্পূর্ণ হয়ে গেলে প্রস্থান করবে ।

আপনি সত্যিই কি করতে চেষ্টা করছেন? নোট করুন যে এই মুহূর্তে আপনার GetList()পদ্ধতিটি সত্যই অ্যাসিঙ্ক হওয়ার দরকার নেই - এটি কোনও আসল কারণ ছাড়াই একটি অতিরিক্ত স্তর যুক্ত করছে। এটি যৌক্তিকভাবে সমান (তবে এর চেয়ে জটিল):

public Task<List<TvChannel>> GetList()
{
    return new GetPrograms().DownloadTvChannels();
}

2
জোন, আমি তালিকায় আইটেমগুলি অবিচ্ছিন্নভাবে পেতে চাই, তবে কেন এই অ্যাসিঙ্কটি এই গেটলিস্ট পদ্ধতিতে উপযুক্ত নয়? তালিকাভুক্ত নয় এবং তালিকার মধ্যে নয়, তবে তালিকার আইটেমগুলিকে সংগ্রহ করা দরকার বলে মনে হয়? আমি যখন async দিয়ে প্রধান পদ্ধতি চিহ্নিত করার চেষ্টা করি তখন আমি "স্ট্যাটিক মেইন পদ্ধতি ধারণ করে না ..."
পাই

@ ডানিওলোভিচ: কী DownloadTvChannels()ফিরবে? সম্ভবত এটি একটি ফেরত Task<List<TvChannel>>দেয় না? যদি তা না হয় তবে আপনি এটির জন্য অপেক্ষা করতে পারবেন এমন সম্ভাবনা কম। (সম্ভাব্য, ওয়েটারের নিদর্শন দেওয়া হলেও অসম্ভব।) Mainপদ্ধতিটি হিসাবে - এটি এখনও অচল হওয়া দরকার ... আপনি সম্ভবত সংশোধকটির সাথে পরিবর্তকটি প্রতিস্থাপন করেছিলেন ? staticasync
জন স্কিটি

হ্যাঁ, এটি যেমনটি বলেছে তেমন একটি টাস্ক <..> দেয়। আমি কীভাবে মূল পদ্ধতির স্বাক্ষরে এ্যাসিঙ্ক স্থাপন করার চেষ্টা করি তা ত্রুটি ছুঁড়ে দেয়। আমি ভিএস 11 প্রিভিউ বিটের উপর বসে আছি!
danielovich

@ ডানিওলোভিচ: এমনকি শূন্য রিটার্ন টাইপের সাথে? শুধু public static async void Main() {}? তবে যদি DownloadTvChannels()ইতিমধ্যে একটি প্রদান করে Task<List<TvChannel>>, সম্ভবত এটি ইতিমধ্যে অ্যাসিনক্রোনাস - সুতরাং আপনাকে অন্য স্তর যুক্ত করার দরকার নেই। এটি যত্ন সহকারে বুঝতে মূল্যবান।
জন স্কিটি

1
@ নওফাল: ফিরে তাকানো, আমার মনে হয় ভিএস ২০১৩ প্রকাশের আগে এটি পরিবর্তন হয়েছিল। সি # 7 এটি পরিবর্তন করে কিনা তা নিশ্চিত নয় ...
জন স্কিটি

4

সি # - সি # 7.1 এর সর্বশেষতম সংস্করণ অ্যাসিঙ্ক কনসোল অ্যাপ্লিকেশন তৈরি করতে দেয়। সি সক্রিয় করার জন্য প্রকল্পে # 7.1, আপনি অন্তত 15.3 আপনার বনাম আপগ্রেড করার আছে, এবং পরিবর্তন সি # সংস্করণ C# 7.1বা C# latest minor version। এটি করতে, প্রকল্পের বৈশিষ্ট্যগুলিতে যান -> বিল্ড -> উন্নত -> ভাষা সংস্করণ।

এর পরে, নিম্নলিখিত কোডগুলি কাজ করবে:

internal class Program
{
    public static async Task Main(string[] args)
    {
         (...)
    }

3

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

using System;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
    public static void Main()
    {
        ShowThreadInfo("Application");

        var t = Task.Run(() => ShowThreadInfo("Task") );
        t.Wait();
    }

    static void ShowThreadInfo(String s)
    {
        Console.WriteLine("{0} Thread ID: {1}",
                          s, Thread.CurrentThread.ManagedThreadId);
    }
}
// The example displays the following output:
//       Application thread ID: 1
//       Task thread ID: 3

উদাহরণ অনুসরণ করে এই বিবৃতি নোট করুন:

উদাহরণগুলি দেখায় যে অ্যাসিক্রোনাস টাস্কটি মূল অ্যাপ্লিকেশন থ্রেডের চেয়ে আলাদা থ্রেডে চালিত করে।

সুতরাং, যদি এর পরিবর্তে আপনি টাস্ক প্রধান কর্মক্ষেত্র থ্রেডে চলে করতে চাই, দেখতে উত্তর দ্বারা @StephenCleary

এবং যে কাজটির উপরে টাস্কটি চালিত হয় সে সম্পর্কে স্টিফেনের জবাব সম্পর্কে মন্তব্যও নোট করুন:

আপনি একটি সাধারণ বা ব্যবহার করতে পারেন এবং এতে কোনও ভুল নেই। তবে সচেতন থাকুন যে দুটি গুরুত্বপূর্ণ পার্থক্য রয়েছে: 1) সমস্ত ধারাবাহিকতা মূল থ্রেডের চেয়ে থ্রেড পুলে চালিত হয় এবং 2) কোনও ব্যতিক্রম একটিতে আবৃত থাকে ।WaitResultasyncAggregateException

( কীভাবে মোকাবেলা করতে ব্যতিক্রম হ্যান্ডলিং অন্তর্ভুক্ত করা যায় তার ব্যতিক্রম হ্যান্ডলিং (টাস্ক সমান্তরাল গ্রন্থাগার) দেখুনAggregateException ))


পরিশেষে, টাস্ক.ডলে মেথড (টাইমস্প্যান) এর ডকুমেন্টেশন থেকে এমএসডিএন-তে , এই উদাহরণটি দেখায় যে কীভাবে একটি অ্যাসিক্রোনাস টাস্ক চালানো যায় যা একটি মান দেয়:

using System;
using System.Threading.Tasks;

public class Example
{
    public static void Main()
    {
        var t = Task.Run(async delegate
                {
                    await Task.Delay(TimeSpan.FromSeconds(1.5));
                    return 42;
                });
        t.Wait();
        Console.WriteLine("Task t Status: {0}, Result: {1}",
                          t.Status, t.Result);
    }
}
// The example displays the following output:
//        Task t Status: RanToCompletion, Result: 42

লক্ষ্য করুন এর পরিবর্তে একটি ক্ষণস্থায়ী delegateথেকে Task.Run, আপনি এর পরিবর্তে একটি ল্যামডা ফাংশন ভালো পাস করতে পারেন:

var t = Task.Run(async () =>
        {
            await Task.Delay(TimeSpan.FromSeconds(1.5));
            return 42;
        });

1

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

class Program
{
    static void Main(string[] args)
    {
        Bootstrapper bs = new Bootstrapper();
        List<TvChannel> list = Task.Run((Func<Task<List<TvChannel>>>)bs.GetList).Result;
    }
}

(theালাই কেবল অস্পষ্টতা সমাধানের জন্য প্রয়োজন)


ধন্যবাদ; টাস্ক.রুনটি গেটলিস্টের অচলাবস্থা সৃষ্টি করে না ()। অপেক্ষা করুন, এই উত্তরটি আরও বেশি উত্সাহ পেয়েছে ...
স্টেফানো

1

আমার ক্ষেত্রে আমার চাকরির একটি তালিকা ছিল যা আমি আমার মূল পদ্ধতি থেকে অ্যাসিঙ্কে চালাতে চেয়েছিলাম, এটি বেশ কিছু সময়ের জন্য উত্পাদনে এটি ব্যবহার করে আসছি এবং সূক্ষ্মভাবে কাজ করে।

static void Main(string[] args)
{
    Task.Run(async () => { await Task.WhenAll(jobslist.Select(nl => RunMulti(nl))); }).GetAwaiter().GetResult();
}
private static async Task RunMulti(List<string> joblist)
{
    await ...
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.