Asp.Net কোর কন্ট্রোলার থেকে IAsyncEnumerable <T> এবং নটফাউন্ডে ফিরছে


10

নিয়ামক পদক্ষেপের জন্য সঠিক স্বাক্ষর কী কী যা একটি IAsyncEnumerable<T>এবং একবার প্রদান করে NotFoundResultতবে একটি অ্যাসিঙ্ক ফ্যাশনে এখনও প্রক্রিয়া করা হয়?

আমি এই স্বাক্ষরটি ব্যবহার করেছি এবং এটি সংকলন করে না কারণ IAsyncEnumerable<T>প্রতীক্ষিত নয়:

[HttpGet]
public async Task<IActionResult> GetAll(Guid id)
{
    try
    {
        return Ok(await repository.GetAll(id)); // GetAll() returns an IAsyncEnumerable
    }
    catch (NotFoundException e)
    {
        return NotFound(e.Message);
    }
}

এটি একটি জরিমানা সংকলন করে তবে এর স্বাক্ষর অ্যাসিঙ্ক নয়। সুতরাং এটি থ্রেড পুলের থ্রেডগুলি ব্লক করবে কিনা তা নিয়ে আমি উদ্বিগ্ন:

[HttpGet]
public IActionResult GetAll(Guid id)
{
    try
    {
        return Ok(repository.GetAll(id)); // GetAll() returns an IAsyncEnumerable
    }
    catch (NotFoundException e)
    {
        return NotFound(e.Message);
    }
}

আমি এটির await foreachমতো একটি লুপ ব্যবহার করার চেষ্টা করেছি তবে এটি অবশ্যই সংকলন করবে না:

[HttpGet]
public async IAsyncEnumerable<MyObject> GetAll(Guid id)
{
    IAsyncEnumerable<MyObject> objects;
    try
    {
        objects = contentDeliveryManagementService.GetAll(id); // GetAll() returns an IAsyncEnumerable
    }
    catch (DeviceNotFoundException e)
    {
        return NotFound(e.Message);
    }

    await foreach (var obj in objects)
    {
        yield return obj;
    }
}

5
আপনি MyObjectএকই সঙ্গে একাধিক আইটেম ফিরে আসছেন id? সাধারণত আপনি এমন কোনও কিছুর NotFoundজন্য প্রেরণ করেননি যা কোনও ফেরত দেয় IEnumerable- এটি খালি হবে - অথবা আপনি অনুরোধকৃত id/ দিয়ে একক আইটেমটি ফিরিয়ে দেবেন NotFound
ক্রোগলডেন

1
IAsyncEnumerableপ্রতীক্ষিত। ব্যবহার await foreach(var item from ThatMethodAsync()){...}
পানাজিওটিস কানভোস

তুমি ফিরে চান তাহলে IAsyncEnumerable<MyObject>, শুধু ফলাফলের যেমন ফিরে return objects। এটি কোনও এইচটিটিপি অ্যাকশনটিকে স্ট্রিমিং জিআরপিসি বা সিগন্যালআর পদ্ধতিতে রূপান্তর করবে না যদিও। মিডলওয়্যারটি এখনও ডেটা গ্রাস করবে এবং ক্লায়েন্টকে একক এইচটিটিপি প্রতিক্রিয়া পাঠাবে
পানাগিওটিস কানভোস

বিকল্প 2 ঠিক আছে। IAsyncEnumerableএএসপি.এনইটি কোর নদীর গভীরতানির্ণয়টি গণনার যত্ন নেয় এবং 3.0 হিসাবে এটি সচেতন।
কર્ક লারকিন

ধন্যবাদ বন্ধুরা. আমি জানি যে আমি এখানে 404 ফেরত দেব না, তবে এটি কেবল একটি স্বীকৃত উদাহরণ। আসল কোডটি বেশ আলাদা। @ কির্কলার্কিন কীটপতঙ্গ হওয়ার জন্য দুঃখিত, তবে আপনি কি 100% নিশ্চিত যে এটি কোনওরকম বাধা সৃষ্টি করবে না? যদি হ্যাঁ, তবে অপশন 2 এর সুস্পষ্ট সমাধান।
ফ্রেডরিক দ্য ফুল

উত্তর:


6

অপশন 2, যা কলটিতে একটি বাস্তবায়ন পাস IAsyncEnumerable<>করে Ok, ঠিক আছে। IAsyncEnumerable<>এএসপি.এনইটি কোর নদীর গভীরতানির্ণয়টি গণনার যত্ন নেয় এবং 3.0 হিসাবে এটি সচেতন।

এখানে প্রসঙ্গটির জন্য পুনরাবৃত্তি হওয়া প্রশ্নটি থেকে কল এসেছে:

return Ok(repository.GetAll(id)); // GetAll() returns an IAsyncEnumerable

কলটি Okএকটি দৃষ্টান্ত তৈরি করে OkObjectResult, যা উত্তরাধিকার সূত্রে প্রাপ্ত ObjectResult। এতে যে মানটি দেওয়া হয়েছে তা Okটাইপযুক্ত object, যা ObjectResultএর Valueসম্পত্তিতে থাকে। এএসপি.নেট কোর এমভিসি কমান্ড প্যাটার্ন ব্যবহার করে , যার মাধ্যমে কমান্ডটি একটি বাস্তবায়ন IActionResultএবং এর প্রয়োগ ব্যবহার করে কার্যকর করা হয় IActionResultExecutor<T>

এর জন্য ObjectResult, এইচটিটিপি প্রতিক্রিয়াতে ObjectResultExecutorপরিণত করতে ব্যবহৃত হয় ObjectResult। এটা বাস্তবায়ন এর ObjectResultExecutor.ExecuteAsyncযে IAsyncEnumerable<>-aware:

public virtual Task ExecuteAsync(ActionContext context, ObjectResult result)
{
    // ...

    var value = result.Value;

    if (value != null && _asyncEnumerableReaderFactory.TryGetReader(value.GetType(), out var reader))
    {
        return ExecuteAsyncEnumerable(context, result, value, reader);
    }

    return ExecuteAsyncCore(context, result, objectType, value);
}

কোডটি দেখায়, Valueসম্পত্তিটি প্রয়োগ করে কিনা তা দেখার জন্য এটি পরীক্ষা করা হয় IAsyncEnumerable<>(বিবরণীতে কলটি গোপন করা আছে TryGetReader)। যদি এটি হয়, ExecuteAsyncEnumerableতাকে বলা হয়, যা গণনা সম্পাদন করে এবং তারপরে অঙ্কিত ফলাফলটি পাস করে ExecuteAsyncCore:

private async Task ExecuteAsyncEnumerable(ActionContext context, ObjectResult result, object asyncEnumerable, Func<object, Task<ICollection>> reader)
{
    Log.BufferingAsyncEnumerable(Logger, asyncEnumerable);

    var enumerated = await reader(asyncEnumerable);
    await ExecuteAsyncCore(context, result, enumerated.GetType(), enumerated);
}

readerউপরের স্নিপেটে যেখানে গণনাটি ঘটে। এটি সামান্য দাফন করা হয়েছে তবে আপনি উত্সটি এখানে দেখতে পাবেন :

private async Task<ICollection> ReadInternal<T>(object value)
{
    var asyncEnumerable = (IAsyncEnumerable<T>)value;
    var result = new List<T>();
    var count = 0;

    await foreach (var item in asyncEnumerable)
    {
        if (count++ >= _mvcOptions.MaxIAsyncEnumerableBufferLimit)
        {
            throw new InvalidOperationException(Resources.FormatObjectResultExecutor_MaxEnumerationExceeded(
                nameof(AsyncEnumerableReader),
                value.GetType()));
        }

        result.Add(item);
    }

    return result;
}

IAsyncEnumerable<>একটি মধ্যে গণিত হয় List<>ব্যবহার await foreach, যা, প্রায় সংজ্ঞা দ্বারা একটি অনুরোধ থ্রেড ব্লক করে না। যেমন পানাজিওটিস কানভোস ওপিতে একটি মন্তব্যে ডেকেছেন , ক্লায়েন্টের কাছে কোনও প্রতিক্রিয়া প্রেরণের আগে এই গণনাটি পুরোপুরি করা হয়।


বিস্তারিত উত্তরের জন্য ধন্যবাদ কર્ક :)। এক উদ্বেগ আমি বিকল্প 2. কর্ম পদ্ধতি নিজেই আমি বুঝলাম যে তার সাথে আছেন ফেরত মান দ্বারা অ্যাসিঙ্ক্রোনাস গণিত করা হবে, কিন্তু এটি একটি ফেরত দেয় না Taskঅবজেক্ট। সেই সত্যটি কি কোনওভাবেই অ্যাসিঙ্ক্রোনসিটি বাধা দেয়? বিশেষত তুলনা করুন, বলুন, একটি অনুরূপ পদ্ধতি যা ফিরে এসেছিল a Task
ফ্রেডরিক দ্য ফুল

1
নাহ, ঠিক আছে। কোনও ফেরত দেওয়ার কোনও কারণ নেই Task, কারণ পদ্ধতিটি নিজেই কোনও অ্যাসিনক্রোনাস কাজ সম্পাদন করে না। এটি উল্লিখিত হিসাবে অ্যাসিক্রোনাস, যা উপরে বর্ণিত হিসাবে পরিচালনা করা হয়। আপনি দেখতে পাচ্ছেন যে Taskসেখানে ব্যবহার করা হয়েছে, কার্যকর করার সময় ObjectResult
কर्क লারকিন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.