c# - সি#সিঙ্ক্রোনাস পদ্ধতি থেকে অ্যাসিঙ্ক্রোনাস পদ্ধতি কল কিভাবে?




async-await (8)

Async Main এখন C # 7.2 এর অংশ এবং উন্নত বিল্ড সেটিংস প্রকল্পগুলিতে সক্ষম করা যেতে পারে।

সি # 7.2 এর জন্য, সঠিক উপায় হল:

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


static async Task MainAsync()
{
   /*await stuff here*/
}

আপনি এটি অনেকগুলি মাইক্রোসফ্ট ডকুমেন্টেশনে ব্যবহৃত দেখতে পাবেন, উদাহরণস্বরূপ: https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-dotnet-how-to-use-topics-subscriptions

আমার কাছে একটি public async void Foo() পদ্ধতি রয়েছে যা আমি সিঙ্ক্রোনাস পদ্ধতিতে কল করতে চাই। যতদূর আমি MSDN ডকুমেন্টেশন থেকে দেখেছি Async পদ্ধতির মাধ্যমে async পদ্ধতিগুলিকে কলিং করছি, কিন্তু আমার পুরো প্রোগ্রামটি অ্যাসাইন পদ্ধতির সাথে নির্মিত হয় না।

এটা কি সম্ভব?

এই পদ্ধতিগুলিকে একটি অ্যাসিঙ্ক্রোনাস পদ্ধতি থেকে কল করার একটি উদাহরণ এখানে রয়েছে: http://msdn.microsoft.com/en-us/library/hh300224(v=vs.110).aspx

এখন আমি সিঙ্ক পদ্ধতি থেকে এই অ্যাসিনসি পদ্ধতি কলিং মধ্যে খুঁজছেন।


অবশেষে আমার সমস্যার সমাধান করে এমন একটি সমাধান যোগ করা, আশা করি কারো সময় বাঁচাবে।

প্রথমত স্টিফেন Cleary একটি দম্পতি নিবন্ধ পড়ুন:

"অ্যাসাইন কোডে ব্লক করবেন না" এর মধ্যে "দুটি সেরা অনুশীলনের" থেকে, প্রথমটি আমার জন্য কাজ করে না এবং দ্বিতীয়টি প্রযোজ্য ছিল না (মূলত যদি আমি await করতে পারি, আমি করি!)।

তাই এখানে আমার Task.Run<>(async () => await FunctionAsync()); : একটি Task.Run<>(async () => await FunctionAsync()); ভিতরে কল মোড়ানো। Task.Run<>(async () => await FunctionAsync()); এবং আশা করছি আর কোন ডিল lock।

এখানে আমার কোড:

public class LogReader
{
    ILogger _logger;

    public LogReader(ILogger logger)
    {
        _logger = logger;
    }

    public LogEntity GetLog()
    {
        Task<LogEntity> task = Task.Run<LogEntity>(async () => await GetLogAsync());
        return task.Result;
    }

    public async Task<LogEntity> GetLogAsync()
    {
        var result = await _logger.GetAsync();
        // more code here...
        return result as LogEntity;
    }
}

আপনি সিঙ্ক্রোনাস কোড থেকে যেকোনো অ্যাসিঙ্ক্রোনাস পদ্ধতি কল করতে পারেন, যা আপনাকে তাদের await করতে হবে যতক্ষণ না, এ ক্ষেত্রে তাদেরকে async হিসাবে চিহ্নিত করতে হবে।

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

আমি সত্যিই আপনি আপনার পদ্ধতি async করতে পারছি না এবং আপনি সিঙ্ক্রোনাস পদ্ধতিটি লক করতে চাই না, তবে আপনাকে টাস্কটিতে ContinueWith পদ্ধতিতে প্যারামিটার হিসাবে পাস করে একটি কলব্যাক পদ্ধতি ব্যবহার করতে হবে।


আমি 100% নিশ্চিত নই, তবে আমি বিশ্বাস করি এই ব্লগে বর্ণিত কৌশলটি অনেক পরিস্থিতিতে কাজ করবে:

আপনি এইভাবে task.GetAwaiter().GetResult() ব্যবহার করতে পারেন যদি আপনি সরাসরি এই প্রচারের যুক্তিটি প্রকাশ করতে চান।


যারা উইন্ডো Async পদ্ধতি একটি নিফটি সামান্য পদ্ধতি আছে AsTask ()। আপনি পদ্ধতিটি নিজেই টাস্ক হিসাবে নিজেকে ফেরত দেওয়ার জন্য ব্যবহার করতে পারেন যাতে আপনি এটিতে প্রত্যক্ষভাবে () কে কল করতে পারেন।

উদাহরণস্বরূপ, উইন্ডোজ ফোন 8 সিলভারলাইট অ্যাপ্লিকেশনটিতে, আপনি নিম্নলিখিতগুলি করতে পারেন:

private void DeleteSynchronous(string path)
{
    StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
    Task t = localFolder.DeleteAsync(StorageDeleteOption.PermanentDelete).AsTask();
    t.Wait();
}

private void FunctionThatNeedsToBeSynchronous()
{
    // Do some work here
    // ....

    // Delete something in storage synchronously
    DeleteSynchronous("pathGoesHere");

    // Do other work here 
    // .....
}

আশাকরি এটা সাহায্য করবে!


যে কেউ এই প্রশ্ন মনোযোগ দিতে ...

যদি আপনি Microsoft.VisualStudio.Services.WebApi TaskExtensionsTaskExtensions নামক একটি ক্লাস আছে। সেই শ্রেণির মধ্যে আপনি স্ট্যাটিক এক্সটেনশান পদ্ধতি Task.SyncResult() দেখতে পাবেন যা সম্পূর্ণ Task.SyncResult() ফেরত না হওয়া পর্যন্ত ব্লক করে।

অভ্যন্তরীণভাবে এটি task.GetAwaiter().GetResult() যা বেশ সহজ, তবে এটি কোনও async পদ্ধতিতে কাজ করার জন্য ওভারলোড করা হয় যা Task , Task<T> বা Task<HttpResponseMessage> ... সিনট্যাক্টিক চিনি, বাচ্চা ... Task<HttpResponseMessage> একটি মিষ্টি দাঁত পেয়েছিলাম।

এটি দেখে মনে হচ্ছে ...GetAwaiter().GetResult() একটি ব্লকিং প্রসঙ্গে ...GetAwaiter().GetResult() কোডটি চালানোর জন্য MS-সরকারী উপায়। আমার ব্যবহারের ক্ষেত্রে জন্য খুব জরিমানা কাজ বলে মনে হয়।


public async Task<string> StartMyTask()
{
    await Foo()
    // code to execute once foo is done
}

static void Main()
{
     var myTask = StartMyTask(); // call your method which will return control once it hits await
     // now you can continue executing code here
     string result = myTask.Result; // wait for the task to complete to continue
     // use result

}

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


var result = Task.Run(async () => await configManager.GetConfigurationAsync()).ConfigureAwait(false);

OpenIdConnectConfiguration config = result.GetAwaiter().GetResult();

অথবা এই ব্যবহার করুন:

var result=result.GetAwaiter().GetResult().AccessToken




async-await