[c#] async सभी तरह से नीचे मुद्दा



Answers

आपको थ्रेड मेसेज पंपों के बारे में सावधान रहना चाहिए और क्या एसिंक वास्तव में करता है नीचे नमूना एक async विधि में कॉल करता है जो दो अन्य async विधियों को कॉल करता है जो वास्तविक कार्य करने के लिए दो कार्य प्रारंभ करते हैं जो 2 और 3 सेकंड प्रतीक्षा करते हैं।

13.00 6520 .ctor Calling async method
13.00 6520 RunSomethingAsync Before
13.00 6520 GetSlowString Before
13.00 5628 OtherTask Sleeping for 2s
15.00 5628 OtherTask Sleeping done
15.00 6520 GetVerySlow Inside
15.00 2176 GetVerySlow Sleeping 3s
18.00 2176 GetVerySlow Sleeping Done
18.00 6520 RunSomethingAsync After GetSlowOtherTaskResultGetVerySlowReturn

जैसा कि आप देख सकते हैं कि कॉल के क्रमबद्ध किए गए हैं, जो प्रदर्शन के बाद जब आप चाहते हैं तो वह नहीं हो सकता है। शायद दो अलग प्रतीक्षा कॉल एक दूसरे पर निर्भर नहीं करते हैं और कार्य के रूप में सीधे शुरू हो सकते हैं।

GetSlowString तक सभी विधियों से पहले यूआई या एएसपी.NET थ्रेड पर कहा जाता है जो एसिंक ऑपरेशन शुरू करते हैं (यदि यह एक संदेश पंप है)। ऑपरेशन के परिणाम के साथ केवल अंतिम कॉल आरंभिक धागा को वापस लहराया जाता है।

पहले से मौजूद धागा को उठाने के लिए प्रस्तुतीकरण दंड कंटेक्स्टस्विच क्षेत्र में कहीं है। यह माइक्रोसेंड का स्तर कहीं पर होना चाहिए। सबसे महंगे सामान प्रबंधित वस्तुओं का निर्माण होगा और कचरा कलेक्टर अस्थायी वस्तुओं को सफाई करेगा। यदि आप इसे एक तंग पाश में कहते हैं, तो आप जीसी बाध्य होंगे क्योंकि वहां एक ऊपरी सीमा है कि कितने धागे बनाए जा सकते हैं। उस स्थिति में टीपीएल आपके कार्यों को कतारों में बफर करेगा, जिसमें मेमोरी आवंटन की आवश्यकता होती है और फिर थ्रेड पूल से एन वर्कर थ्रेड्स के साथ कतारें निकालें।

मेरे कोर I7 पर मुझे प्रत्येक कॉल के लिए 2 एमआईसीआरसीकेंड का ओवरहेड मिलता है (डीबग.प्रति रेखा पर टिप्पणी करें) और एक डब्ल्यूपीएफ एप्लीकेशन में 5 लाख कॉल के लिए 6,5 जीबी की मेमोरी खपता है जो आपको प्रति एसिंक्रोनस ऑपरेशन चेन प्रति 130KB का स्मृति ओवरहेड देता है । यदि आप उच्च स्केलेबिलिटी के बाद हैं, तो आपको अपने जीसी के बाद देखना होगा। जो डफी ने अपनी नई भाषा समाप्त होने तक हमें वर्तमान में CLR का उपयोग करना होगा।

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        Print("Calling async method");
        RunSomethingAsync();
    }

    private async void RunSomethingAsync()
    {
        Print("Before");
        string msg = await GetSlowString();
        Print("After " + msg);
        cLabel.Content = msg;
    }

    void Print(string message, [CallerMemberName] string method = "")
    {
        Debug.Print("{0:N2} {1} {2} {3}", DateTime.Now.Second, AppDomain.GetCurrentThreadId(), method, message);
    }

    private async Task<string> GetSlowString()
    {
        Print("Before");

        string otherResult = await OtherTask();

        return "GetSlow" + otherResult + await GetVerySlow(); ;
    }

    private Task<string> OtherTask()
    {
        return Task.Run(() =>
        {
            Print("Sleeping for 2s");
            Thread.Sleep(2 * 1000);
            Print("Sleeping done");
            return "OtherTaskResult";
        });
    }

    private Task<string> GetVerySlow()
    {
        Print("Inside");
        return Task.Run(() =>
        {
            Print("Sleeping 3s");
            Thread.Sleep(3000);
            Print("Sleeping Done");
            return "GetVerySlowReturn";
        });
    }
}
Question

मेरे पास एक async asp.net नियंत्रक है यह नियंत्रक एक async विधि को कॉल करता है विधि जो वास्तव में async IO काम करता है मेरे आवेदन में गहराई से नीचे है नियंत्रक और श्रृंखला में अंतिम पद्धति के बीच के तरीकों की श्रृंखला सभी को एसिंक मॉडिफ़र के साथ चिह्नित किया गया है। यहां एक उदाहरण है कि मेरे पास कोड सेटअप कैसे है:

public async Task<ActionResult> Index(int[] ids)
{
    List<int> listOfDataPoints = dataPointService(ids);
    List<Task> dpTaskList = new List<Task>();
    foreach (var x in listOfDataPoints)
    {
        dpTaskList.Add(C_Async(x));
    }

    await Task.WhenAll(dpTaskList);
    return View();
}


private async Task C_Async(int id)
{
    //this method executes very fast
    var idTemp = paddID(id);
    await D_Async(idTemp);
}

private async Task D_Async(string id)
{
    //this method executes very fast
    await E_Async(id);
}

private async Task E_Async(string url)
{
    //this method performs the actual async IO
    result = await new WebClient().DownloadStringTaskAsync(new Uri(url))
    saveContent(result);
}

जैसा कि आप देख सकते हैं कि नियंत्रक C_Async (x) को एसिंक्रोनस रूप से कॉल करता है, तो एएसएनसी तरीके की एक श्रृंखला E_Async है नियंत्रक और E_Async के बीच विधियां हैं और सभी के पास एसिंक मॉडरिफ़र है। क्या कोई प्रदर्शन जुर्माना है क्योंकि एसिंक संशोधक का उपयोग करने के तरीकों पर कोई भी एसिंक आईओ काम नहीं कर रहा है?

नोट: यह वास्तविक कोड का सरलीकृत संस्करण है, नियंत्रक और E_Async विधि के बीच अधिक async विधियां हैं।




Links