आपके C# एप्लिकेशन को कतारों और बैकग्राउंड टास्क की आवश्यकता क्यों है?
\n\nकल्पना करें: आप C# में एक वेब एप्लिकेशन चला रहे हैं, उपयोगकर्ता "रिपोर्ट भेजें" बटन दबाता है, और... सर्वर 30 सेकंड के लिए हैंग हो जाता है जब तक PDF जनरेट नहीं हो जाती। परिचित लग रहा है? 2024 में उपयोगकर्ता धीमेपन को माफ नहीं करते। समाधान है — कतारें और बैकग्राउंड टास्क। वे सिंक्रोनस अराजकता को एसिंक्रोनस स्वर्ग में बदल देते हैं।
\n\nइस लेख में, हम C# में बैकग्राउंड प्रोसेसिंग को सही तरीके से व्यवस्थित करने के तरीके पर चर्चा करेंगे: बिल्ट-इन Channel<T> से लेकर इंडस्ट्रियल-ग्रेड RabbitMQ तक। आप सीखेंगे कि कैसे भारी काम को मुख्य थ्रेड से बाहर निकालें, बिना आर्किटेक्चर को तोड़े। चलिए शुरू करते हैं!
C# में टास्क कतार क्या है और इसकी आवश्यकता क्यों है?
\n\nकतार (queue) एक FIFO (First In, First Out) डेटा संरचना है। C# के संदर्भ में, यह एक तंत्र है जो किसी कार्य के निष्पादन को स्थगित करने की अनुमति देता है ताकि मुख्य थ्रेड ब्लॉक न हो। बैकग्राउंड टास्क वह कोड है जो "पर्दे के पीछे" चलता है, जबकि उपयोगकर्ता साइट पर क्लिक करना जारी रखता है।
\n\nसामान्य परिदृश्य:
\n- \n
- ईमेल सूचनाएं भेजना (100 ईमेल — SMTP के लिए 100 अनुरोध) \n
- रिपोर्ट और Excel फ़ाइलें जनरेट करना \n
- अपलोड की गई छवियों को प्रोसेस करना (रीसाइज़, वॉटरमार्क) \n
- बाहरी API के साथ एकीकरण (धीमी प्रतिक्रियाएं) \n
- डेटाबेस में लॉगिंग (UI को धीमा न करने के लिए) \n
कतारों के बिना, C# एप्लिकेशन हर भारी अनुरोध पर "अटक" जाएगा। कतारों के साथ — आप बस कार्य को बफर में डालते हैं और उपयोगकर्ता को जवाब देते हैं: "हो गया, हम प्रोसेस कर रहे हैं।"
\n\nविकल्प 1: BackgroundService के माध्यम से बैकग्राउंड टास्क (बिल्ट-इन .NET)
\n\nसबसे आसान तरीका Microsoft.Extensions.Hosting से BackgroundService का उपयोग करना है। यह ASP.NET Core में बैकग्राउंड सर्विसेज बनाने के लिए बेस क्लास है। यह सरल परिदृश्यों के लिए एकदम सही है जब जटिल मैसेज रूटिंग की आवश्यकता नहीं होती है।
उदाहरण: Channel<T> के साथ बैकग्राउंड हैंडलर
\n\nचलिए एक सरल Producer-Consumer लिखते हैं। Producer (कंट्रोलर) कार्य को चैनल में डालता है, Consumer (BackgroundService) उसे लेता है और निष्पादित करता है।
\n\n// चरण 1. चैनल बनाएं (थ्रेड-सेफ कतार)\npublic class TaskChannel\n{\n private readonly Channel<string> _channel = \n Channel.CreateBounded<string>(new BoundedChannelOptions(100)\n {\n FullMode = BoundedChannelFullMode.Wait\n });\n\n public ChannelWriter<string> Writer => _channel.Writer;\n public ChannelReader<string> Reader => _channel.Reader;\n}\n\n// चरण 2. BackgroundService जो चैनल से पढ़ता है\npublic class EmailBackgroundService : BackgroundService\n{\n private readonly TaskChannel _taskChannel;\n\n public EmailBackgroundService(TaskChannel taskChannel)\n {\n _taskChannel = taskChannel;\n }\n\n protected override async Task ExecuteAsync(CancellationToken stoppingToken)\n {\n await foreach (var emailData in _taskChannel.Reader.ReadAllAsync(stoppingToken))\n {\n // ईमेल भेजने का अनुकरण (2 सेकंड)\n await Task.Delay(2000, stoppingToken);\n Console.WriteLine($"ईमेल भेजा गया: {emailData}");\n }\n }\n}\n\n// चरण 3. कंट्रोलर जो कार्य डालता है\n[ApiController]\n[Route("api/email")]\npublic class EmailController : ControllerBase\n{\n private readonly TaskChannel _taskChannel;\n\n public EmailController(TaskChannel taskChannel)\n {\n _taskChannel = taskChannel;\n }\n\n [HttpPost("send")]\n public IActionResult SendEmail([FromBody] string emailData)\n {\n _taskChannel.Writer.TryWrite(emailData);\n return Accepted(new { message = "ईमेल कतार में डाल दिया गया" });\n }\n}\n\n// चरण 4. Program.cs में रजिस्ट्रेशन\nbuilder.Services.AddSingleton<TaskChannel>();\nbuilder.Services.AddHostedService<EmailBackgroundService>();\n\nयहाँ क्या हो रहा है? उपयोगकर्ता POST /api/email/send कॉल करता है — डेटा चैनल में आ जाता है