आग और मत काफी बिना राज्य के एपीअल - एपलेंट चलाया जाना भूल जाओ
अधिकांश अतुल्यकालिक व्यवस्थाओं को या तो बहुत ज्यादा याद है (लॉग, कतारों, कचरा आप कभी नहीं चाहते थे)... या वे कुछ भी याद नहीं करते हैं (आग और तारवाले काले छेद कि पल कुछ गलत हो जाता है).
यह लेख कुछ अलग प्रस्तुत करता है:
एक तरीका जहाँ हर बार अतुल्यकालिक ऑपरेशन छोटी हो जाता है ट्रैक योग्य, निरीक्षण योग्य, फिर से चालू करें (p), स्वयं को शुद्ध कर रहा है कार्य इकाई - और पूरे प्रणाली निजी रहता है, बाध्य, तेजी से, और अनुमान लगाना।
यह मेरे पहले लेख का साथी है, **LRUS - जब तेज़ क्षमता आपके तंत्र को बेहतर बनाती है**यही कारण है कि एक जाँच ने दिखाया कि स्मृति + पार करना एक जीवित व्यवस्था बन जाता है।
यह एक अन्य आधे का पता लगाता है: बाध्य किया, एनहेर्निक चलाने वाला@ info: whatsthis - किस तरह सक्रिय कार्य का एक छोटा सा सफर हो जाता है, एक घटना लॉग और एक रीप्ले इंजन, बिना किसी उपयोगकर्ता डाटा को रखे.
उदाहरण मेरे चिट्ठे के अनुवाद विजेट - एक छोटे से यूआई से आता है का अनुवाद करने के लिए चित्र-चना पर सामग्री का अनुवाद करने के लिए। यह मामूली लग रहा है।
यह है पार्ट 1 दो भाग श्रंखला के लिए:
- पार्ट 1 (यह लेख): सिद्धांत, पैटर्न, और एक वास्तविक उदाहरण
- पार्ट 2: नयी लाइब्रेरी बनाना: Git मिट्टी के साथ पूरा कार्यान्वयन
नहीं!
अब यह विशेष रूप से अल्पतम पैकेज में है 20 से अधिक।.
समस्या - असंभावी कार्य छुपा हुआ राज्य बनाता है
एनईएस.ईटी विकासकर्ता तीन बुरी विकल्प से चुनने के लिए कर रहे हैं:
थके माँदे दहकती हुई आग में दाखिल होंगे
आप Task.Run() कुछ, आशा है कि यह समाप्त होता है, और जब यह आप कुछ भी नहीं मिलता है.
थके माँदे दहकती हुई आग में दाखिल होंगे
आप ब्लॉक ब्लॉक ब्लॉक ब्लॉक नहीं करना चाहिए. नीचे दिए गए विस्फोटों से मर जाते हैं. आपके उपयोक्ता तुम से नफरत करते हैं.
हर जगह क़तार/ मुक़र्रर किए जा रहे हैं
अब आपके पास है:
- भारी क़तार
- आग्रहित स्थिति आप रखने के लिए मतलब नहीं था
- PIII बिना कहीं जमा करें
- एक वितरित तंत्र जहाँ आप सिर्फ एक साधारण आपरेशन चाहते थे
यु. पू.
उपयोगी... लेकिन बाहरी. साथ ही: यह कुछ भी खेल नहीं सकता और अक्सर लीक डेटा आप कभी स्टोर करने के लिए इरादा नहीं किया था.
हम वास्तव में क्या चाहते हैं:
- छोटा जीवन
- निजी
- डिबग संपादन योग्य
- निरीक्षण योग्य
- बाध्य किया गया
- यदि आवश्यक हो तो प्राप्त करने में अक्षम
- और फिर चला गया
"सिर्फ काफी लंबे समय" की याद क्या प्रणाली कर रही है और कुछ और नहीं.
पैटर्न - आग और काफी नहीं है भूल जाना
यहाँ एक वाक्य में विचार है:
किक ऑपरेशन तुरंत बंद कर देता है, यह एक कार्य - विशेष रूप से एक कार्यीय स्रोत के माध्यम से, इसे साफ़ कर देता है, और अंतिम कुछ कार्यों की एक छोटी - सी धारा को साफ़ रखता है ताकि आप उन्हें किसी उपयोगकर्ता की सामग्री का निरीक्षण कर सकते हैं या निकाल सकते हैं ।
यह बीच में बैठता है:
- घटना क्लीक्सिंग
- जान - पहचानवालों के लिए
- कार्य कतार
- भविष्य/ चेतावनी
- एफील सत्र
... उनमें से किसी के बिना।
flowchart TB
subgraph Client["Client Request"]
R[Start Translation]
end
subgraph API["API Layer"]
A[Create TaskId] --> B[Create TaskCompletionSource]
B --> C[Queue to Channel]
C --> D[Return TaskId Immediately]
end
subgraph Cache["Ephemeral Cache (Bounded)"]
E[Store TranslateTask]
F[Max 5 per user]
G[6hr absolute / 1hr sliding expiry]
end
subgraph Worker["Background Worker"]
H[Read from Channel]
H --> I[Execute Translation]
I --> J[Complete TCS]
end
R --> A
B --> E
E --> F --> G
C --> H
style Cache fill:none,stroke:#10b981,stroke-width:2px
style Worker fill:none,stroke:#6366f1,stroke-width:2px
एक एपीटीम कार्य की एओटोमी
कोर डाटा स्ट्रक्चर एक है TranslateTask - एक द्वारा वापस किया गया एक छोटा सा परमाणु इकाई Task<TaskCompletion>:
// From TranslateTask.cs
public class TranslateTask(
string taskId,
DateTime startTime,
string language,
Task<TaskCompletion>? task)
: TranslateResultTask(taskId, startTime, language)
{
public Task<TaskCompletion>? Task { get; init; } = task;
}
public record TaskCompletion(
string? TranslatedMarkdown,
string OriginalMarkdown,
string Language,
bool Complete,
DateTime? EndTime);
इसमें समाहित है:
- एक अद्वितीय आईडी (पूरी प्रवाह पर प्रभावी)
- समयबद्ध (जब यह शुरू हुआ)
- मेटाडाटा (अनुप्रयोगिक - उपयोक्ता सामग्री!)
- वास्तविक का संदर्भ
Task<TaskCompletion> - अवधि ( एक्सेस पर बन्द किया गया)
- त्रुटि स्थिति (कार्य स्थिति से संचालित है)
- अंतिम परिणाम (सिर्फ अगर सफलतापूर्वक पूर्ण हो गया)
यही कारण है कि कुछ भी नहीं था, डिस्क में कुछ भी नहीं लिखा गया है. कोई भी नहीं है जो एक रोलिंग विंडो से परे है.
AWS के पास कदम फंक्शन्स है. AWECANECANEANEANE. आप के बीच में है. आप के 30 लाइन है कि एक बादल के बिल की आवश्यकता नहीं है.
टास्क-क्लीय संसाधन पैटर्न - आग- तथा- ट्रैक के लिए भूल गया
जादू में होता है BackgroundTranslateServiceहम एक का उपयोग करने के बजाय, आग और तार के बजाय, हम एक का इस्तेमाल करते हैं कार्य - एक वादा के रूप में बना कि हमें जल्दी वापस आने देता है... ... जबकि काम पृष्ठभूमि में होता है.
// From BackgroundTranslateService.cs
private readonly Channel<(PageTranslationModel, TaskCompletionSource<TaskCompletion>)>
_translations = Channel.CreateUnbounded<(PageTranslationModel, TaskCompletionSource<TaskCompletion>)>();
private async Task<Task<TaskCompletion>> Translate(PageTranslationModel message)
{
// Create a TaskCompletionSource that will eventually hold the result
var tcs = new TaskCompletionSource<TaskCompletion>();
// Send the translation request along with the TCS to be processed
await _translations.Writer.WriteAsync((message, tcs));
// Return the Task immediately -caller can await it or check status later
return tcs.Task;
}
क्या एक कार्य- पूर्णता स्रोत है?
यदि आप उपयोग नहीं किया है TaskCompletionSource<T> पहले, इसके बारे में एक के रूप में सोचो वादा करता है कि आप दस्ती रूप से नियंत्रित करेंनियमित तौर पर नहीं Task जो कि जब समाप्त हो जाए तो समाप्त हो जाता है टीसीएस पूर्ण आप कॉल SetResult(), SetException(), या SetCanceled().
यह आपको देता है:
- एक बार फिर जाएँ
Task(और) बुलाने वाले की तरफ - वास्तविक कार्य कहीं अन्य (परेशन थ्रेड, पृष्ठभूमि सेवा इत्यादि) करें.
- कार्य को पूरा करें जब आप यह किया जाता है तय करें
यह "आग-से- भूलें" और "आग और ट्रैक" के बीच पुल है.
एपीआई परत - अनुवाद शुरू करना
जब उपभोक्ता क्लिक करे "सही", तो सामनेवाले को एपीआई कॉल करना:
// From translations.js
fetch('/api/translate/start-translation', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
Language: shortCode,
OriginalMarkdown: markdown
})
})
.then(response => response.json())
.then(taskId => {
// Got a taskId immediately -translation is running in background
console.log("Task ID:", taskId);
// Poll for updates via HTMX
htmx.ajax('get', "/editor/get-translations", {
target: '#translations',
swap: 'innerHTML'
});
});
NORD तुरंत कार्य ID के साथ लौटाता है:
// From TranslateAPI.cs
[HttpPost("start-translation")]
public async Task<Results<Ok<string>, BadRequest<string>>> StartTranslation(
[FromBody] MarkdownTranslationModel model)
{
if (!backgroundTranslateService.TranslationServiceUp)
return TypedResults.BadRequest("Translation service is down");
// Create a unique identifier for this translation task
var taskId = Guid.NewGuid().ToString("N");
var userId = Request.GetUserId(Response);
// Trigger translation -returns Task<TaskCompletion> immediately
var translationTask = await backgroundTranslateService.Translate(model);
// Wrap it in our trackable TranslateTask
var translateTask = new TranslateTask(taskId, DateTime.Now, model.Language, translationTask);
// Store in the ephemeral cache (bounded, self-cleaning)
translateCacheService.AddTask(userId, translateTask);
// Return the task ID to the client -they can poll for status
return TypedResults.Ok(taskId);
}
प्रतिक्रिया त्वरित है. वास्तविक अनुवाद पृष्ठभूमि में चलाता है. उपयोक्ता को पोल कर सकता है या सिर्फ यूआई अद्यतन देख सकता है.
रोलिंग ऑपरेशन विंडो - AA-A आत्म साफिंग बफर
वह खास समझ जो हमारी समझ से परे है एलआरयू लेख यहाँ भी लागू करें:
तंत्र के बारे में डिबग और कारण रखने के लिए बस पर्याप्त इतिहास रखें... और प्राकृतिक सड़न सब कुछ और.
// From TranslateCacheService.cs
public class TranslateCacheService(IMemoryCache memoryCache)
{
public void AddTask(string userId, TranslateTask task)
{
if (memoryCache.TryGetValue(userId, out CachedTasks? tasks))
{
var currentTasks = tasks?.Tasks ?? new List<TranslateTask>();
currentTasks = currentTasks.OrderByDescending(x => x.StartTime).ToList();
// Keep only the 5 most recent tasks -bounded window
if (currentTasks.Count >= 5)
{
var lastTask = currentTasks.Last();
currentTasks.Remove(lastTask);
}
currentTasks.Add(task);
currentTasks = currentTasks.OrderByDescending(x => x.StartTime).ToList();
tasks!.Tasks = currentTasks;
memoryCache.Set(userId, tasks, new MemoryCacheEntryOptions
{
AbsoluteExpiration = tasks.AbsoluteExpiration,
SlidingExpiration = TimeSpan.FromHours(1)
});
}
else
{
// First task for this user
var cachedTasks = new CachedTasks
{
Tasks = new List<TranslateTask> { task },
AbsoluteExpiration = DateTime.Now.AddHours(6)
};
memoryCache.Set(userId, cachedTasks, new MemoryCacheEntryOptions
{
AbsoluteExpiration = cachedTasks.AbsoluteExpiration,
SlidingExpiration = TimeSpan.FromHours(1)
});
}
}
public List<TranslateTask> GetTasks(string userId)
{
if (memoryCache.TryGetValue(userId, out CachedTasks? tasks))
return tasks?.Tasks ?? new List<TranslateTask>();
return new List<TranslateTask>();
}
private class CachedTasks
{
public List<TranslateTask> Tasks { get; set; } = new();
public DateTime AbsoluteExpiration { get; set; }
}
}
हर नया कार्य:
- उपयोक्ता के चल रहे विंडो में जोड़ा गया है
- अगर हम क्षमता में हैं तो सबसे पुराने दबाएँ (5 अधिकतम)
- 6 घंटे के बाद सारे प्रयास (लम्बित) या 1 घंटे की निष्क्रियता के बाद)
flowchart LR
subgraph Window["Per-User Task Window (Max 5)"]
T1[Oldest Task] --- T2[Older] --- T3[Recent] --- T4[Newer] --- T5[Newest]
end
New[New Task] -->|Enqueue| Window
T1 -->|Evicted| Gone[(Expired)]
style Window fill:none,stroke:#10b981,stroke-width:2px
style Gone fill:none,stroke:#ef4444,stroke-width:2px
कोई फिर से ख़तरा नहीं है. कैश में कोई PIII I (सिर्फ कार्य आईडी, समय- अवधि, और भाषा कोड) में नहीं है ।
सीमा छूटी - राज्यपाल लूप
पृष्ठभूमि सेवा एक के लिए लागू होती है स्थिर विश्वास एक चैनल रीडर व गुण के प्रयोग से लूप करें Task.WhenAny:
// From BackgroundTranslateService.cs
private async Task TranslateFilesAsync(CancellationToken cancellationToken)
{
var processingTasks = new List<Task>();
while (!cancellationToken.IsCancellationRequested)
{
// Fill up to IPCount concurrent tasks (e.g., 4 parallel translations)
while (processingTasks.Count < markdownTranslatorService.IPCount &&
!cancellationToken.IsCancellationRequested)
{
var item = await _translations.Reader.ReadAsync(cancellationToken);
var translateModel = item.Item1;
var tcs = item.Item2;
// Start the task and add it to the list
var task = TranslateTask(cancellationToken, translateModel, item, tcs);
processingTasks.Add(task);
}
// Wait for ANY of the tasks to complete
var completedTask = await Task.WhenAny(processingTasks);
processingTasks.Remove(completedTask);
// Handle exceptions if needed
try
{
await completedTask;
}
catch (Exception ex)
{
logger.LogError(ex, "Error translating markdown");
}
}
}
यह एक तरह है भाप इंजन पर राज्यपाल▪ तनाव कम करने से तनाव कम होता है ।
यह पैटर्न आपको देता है:
- सर्पिल - असीमित कार्यों की व्याख्या नहीं कर सकता
- सॉफ्ट असली समय व्यवहार -बहुत देर हो गई
- स्वाभाविक कूट - कूटनेवाले जोड़े - दृढ़तापूर्वक बफरों के लिए
- लोड होने पर स्थिरता - स्वादिष्ट रूप से।
टास्क कम्प्लीशन स्रोत पूरा करना
जब वास्तविक अनुवाद कार्य समाप्त होता है, हम टीसीएस पूरा करते हैं:
// From BackgroundTranslateService.cs
private async Task TranslateTask(
CancellationToken cancellationToken,
PageTranslationModel translateModel,
(PageTranslationModel, TaskCompletionSource<TaskCompletion>) item,
TaskCompletionSource<TaskCompletion> tcs)
{
try
{
await retryPolicy.ExecuteAsync(async () =>
{
// Do the actual translation work
var translatedMarkdown = await markdownTranslatorService.TranslateMarkdown(
translateModel.OriginalMarkdown,
translateModel.Language,
cancellationToken);
// SUCCESS: Complete the TCS with the result
tcs.SetResult(new TaskCompletion(
translatedMarkdown,
translateModel.OriginalMarkdown,
translateModel.Language,
true,
DateTime.Now));
});
}
catch (TranslateException e)
{
// FAILURE: Complete the TCS with an exception
tcs.SetException(new Exception($"Translation failed after 3 retries: {e.Message}"));
}
catch (Exception e)
{
// UNEXPECTED: Complete the TCS with the exception
tcs.SetException(e);
}
}
कॉलर का Task<TaskCompletion> - जो वे तुरंत मिल गया जब वे बुलाया Translate() - वे कर सकते हैं:
awaitयह अगर वे ब्लॉक करना चाहते हैं- जाँचें
IsCompletedसर्वे करने के लिए - जाँचें
IsFaultedदेखना है कि क्या यह असफल हो गया है - जाँचें
Resultजिस अंक में ये लेख भी हैं
प्रस्थिति परियोजना - कार्य से सरकार का पालन करना
जब उपयोक्ता को कार्यों को प्रदर्शित किया जाता है, हम जीवित कार्य को दृश्य मॉडल में रखते हैं:
// From TranslateTask.cs
public TranslateResultTask(TranslateTask task, bool includeMarkdown = false)
{
TaskId = task.TaskId;
StartTime = task.StartTime;
Language = task.Language;
// Check for faulted state first -a faulted task is also "completed" in .NET terms
if (task.Task?.IsFaulted == true)
{
Failed = true;
Completed = false;
TotalMilliseconds = (int)(DateTime.Now - task.StartTime).TotalMilliseconds;
}
else if (task.Task?.IsCompletedSuccessfully == true)
{
Completed = true;
Failed = false;
var endTime = task.Task.Result.EndTime;
TotalMilliseconds = (int)((endTime - task.StartTime)!).Value.TotalMilliseconds;
EndTime = endTime;
}
else
{
// Still in progress
Completed = false;
Failed = false;
TotalMilliseconds = (int)(DateTime.Now - task.StartTime).TotalMilliseconds;
}
if (Completed && includeMarkdown)
{
var result = task.Task?.Result;
if (result == null) return;
OriginalMarkdown = result.OriginalMarkdown;
TranslatedMarkdown = result.TranslatedMarkdown;
}
}
कार्य अवस्था पर एक टिप्पणी
.नेट't Task कुछ quky राज्य संयोजन है:
IsCompletedके लिए सही है दोनों सफल हो गया तथा गलती की हुई कार्यIsCompletedSuccessfullyसफलता के लिए केवल सही हैIsFaultedइसका अर्थ है कि इसने एक अपवाद निकालाIsCanceledइसका अर्थ है कि यह रद्द किया गया था
तो आपको जांच करनी चाहिए IsFaulted जाँच से पहले IsCompleted, या आप सफलता के रूप में असफलों का इलाज करेंगे.
यूआई -HMX पोलिंग
HMMX के उपयोग से अद्यतन के लिए दृश्य सर्वे hx-trigger:
@* From _GetTranslations.cshtml *@
@{
var allCompleted = Model.All(x => x.Completed);
var trigger = allCompleted ? "none" : "every 5s";
}
<div class="translationpoller"
hx-get="/editor/get-translations"
hx-swap="outerHTML"
hx-trigger="@trigger">
<table class="table">
@foreach (var item in Model)
{
<tr>
<td>
@if (item.Completed)
{
<a href="#" x-on:click.prevent="viewTranslation('@item.TaskId')">View</a>
}
else if (item.Failed)
{
<text>Failed</text>
}
else
{
<text>Processing</text>
}
</td>
<td>
@if (item.Completed)
{
<i class='bx bx-check text-green'></i>
}
else if (item.Failed)
{
<i class='bx bx-x text-red'></i>
}
else
{
<img src="~/img/3-dots-bounce.svg" />
}
</td>
<td>@item.Language</td>
<td>@TimeSpan.FromMilliseconds(item.TotalMilliseconds).Humanize()</td>
</tr>
}
</table>
</div>
चतुर सा: hx-trigger="@trigger" स्थिति पर आधारित परिवर्तन:
- यदि कार्य अभी भी चल रहा है: हर 5 सेकंड
- यदि सभी कार्य किए जाते हैं: खर्च बन्द करना बन्द करें (a)
"none")
यह है खुद को ज़बरदस्त मार रहे हैं - यह देखने के लिए कुछ भी नहीं है जब स्वचालित बंद हो जाता है.
परिणाम पुनःप्राप्त कर रहा है
जब उपयोक्ता क्लिक करे "View - >", हम पूरा अनुवाद लाते हैं:
// From TranslateAPI.cs
[HttpGet("get-translation/{taskId}")]
public async Task<Results<JsonHttpResult<TranslateResultTask>, BadRequest<string>>> GetTranslation(
string taskId)
{
var userId = Request.GetUserId(Response);
var tasks = translateCacheService.GetTasks(userId);
var translationTask = tasks.FirstOrDefault(t => t.TaskId == taskId);
if (translationTask == null)
return TypedResults.BadRequest("Task not found");
// Include the markdown content in the response
var result = new TranslateResultTask(translationTask, includeMarkdown: true);
return TypedResults.Json(result);
}
जावास्क्रिप्ट तब संपादक देता है:
// From translations.js
export function viewTranslation(taskId) {
fetch(`/api/translate/get-translation/${taskId}`)
.then(response => response.json())
.then(data => {
// Show the translated content area
document.getElementById("translatedcontent").classList.remove("hidden");
// Populate the editors
var originalMde = window.mostlylucid.simplemde.getinstance('translatedcontentarea');
originalMde.value(data.originalMarkdown);
var mde = window.mostlylucid.simplemde.getinstance('markdowneditor');
mde.value(data.translatedMarkdown);
});
}
यह गोपनीयता-पी क्यों है
क्योंकि:
- कैश में कोई उपयोक्ता सामग्री भंडारित नहीं है - केवल मेटाडाटा (डी, समय- चिह्न, भाषा)
- कार्य परिणाम में केवल सामग्री मौजूद है -जो स्मृति में है, कार्य से संलग्न है
- विंडो बाध्य किया गया है - अधिकतम 5 कार्य प्रति उपयोक्ता, अधिकतम 6 घंटे रीग्रेसन
- हर चीज सड़ता है स्वाभाविक - अक्रिय उपयोक्ताों को साफ करने में सक्षम
- डिस्क से कोई नहीं मिला - कोई लॉग, कोई कतार, कोई डाटाबेस नहीं
- आप गलती से पीआई को रोक नहीं सकते - वहाँ जाने के लिए कोई जगह नहीं है
यह वस्तुओं की रचना है मैं चाहते हैं कि ब्राउज़र तथा फ्रन्टएण्ड फ्रेमवर्क का उपयोग सत्र संचालन के लिए किया गया था.
व्यवहार
आप बहुत कठिन सोच के बिना क्या मिलता है:
एल. एल.) |---------|-----| | स्थिरता % 1 ने चैनल के माध्यम से जानकारी के आधार पर अनुमान लगाया: | ऋणात्मक फ़ीडबैक लूप ✔ याद रखने के लिए तनाव कम करने के साथ - साथ उसे कम - से - कम कुछ और लोड करने की कोशिश कीजिए । | डिबग गपशप निरीक्षण करने के लिए सही आपरेशन बस काफी लंबे समय के लिए मौजूद हैं | पुनःप्राप्त करने की क्षमता SpamAssassin सफलतापूर्वक समाप्त हो गया | शून्य डेटा फिर से गणना एक बार कामों के लिए गोपनीयता तथा सरल सुधार | चलाने के लिए स्वयं का चयन किया जा रहा है पुराना काम खत्म हो जाता है, BAR
वैसे ही LRU कैश ने व्यवहार की स्मृति को तेज़ किया है, जो दबा हुआ ऑपरेशन विंडो मृत्यु के दृष्टिकोण को तेज़ करता है ।
इस पैटर्न का इस्तेमाल करते वक्त
इसे प्रयोग करें जब:
- उपयोक्ता डाटा कॉन्फ़िगर नहीं करना चाहिए
- संचालन छोटे समय के लिए हैं (मिनटों में)
- डिबगिंग मामलों को समझा जा रहा है
- गोपनीयता
- स्थिर बातों को लोड करें
- आप तत्काल प्रतिक्रिया + पृष्ठभूमि प्रक्रिया चाहते हैं
इसे प्रयोग न करें:
- आपको सही अनुक्रम की आवश्यकता है (एक वास्तविक कतार का उपयोग करें)
- संचालन घंटे लेते हैं (माना आग या समान)
- आप वास्तव में एक वितरित ट्रांजेक्शन की जरूरत है (एक वितरित ट्रांजेक्शन प्रयोग करें)
- बहुत से सर्वरों को निर्देशांकों की आवश्यकता है (पुष्टि का उपयोग करें)
मगर फिर भी, सा. यु.
यदि है एलआरयू लेख के बारे में था भूल जाने के द्वारा सीखना, यह एक के बारे में है प्रीपिंग द्वारा चलाया जा रहा है.
यह प्रणाली वास्तव में सहायक - और अधिक कुछ भी नहीं होने के लिए पर्याप्त याद करती है ।
यह है:
- बाध्य किया गया
- अनुमानित
- निजी
- डिबग संपादन योग्य
- पाने योग्य
- स्वयं को साफ कर रहा है
- मजबूत
- और हम ही ने (सूरज) को रौशन चिराग़ बनाया
सबसे अच्छी बात है? आप पहले से ही यह कैसे लागू करें: एक TaskCompletionSource, एक Channel, एक IMemoryCache धीरे - धीरे बीतता जा रहा है और एक पृष्ठभूमि का काम करता है ।
आग ... और काफी भूल नहीं है.
अगला क्या है?
में पार्ट 2: नयी लाइब्रेरी बनाना, हम इस पैटर्न को एक ड्रॉप इन सहायता में बदल देंगे:
EphemeralForEachAsync<T>- जैसेParallel.ForEachAsyncलेकिन ऑपरेशन के साथ- प्रति लक्ष्य अनुक्रम वध हेतु कुंजी
EphemeralWorkCoordinator<T>- एक लंबे समय से दिखाई दे रहे कार्य कतार- नामित/ टाइप संयोजक के साथ
AddEphemeralWorkCoordinator<TCoordinator>(की तरहAddHttpClient) - स्कोप तथा एकलटन जीवन भर के साथ पूरा डील संयोजन
- अन्य आगमन से तुलना (टीपी डाटा फ्लो, चैनल्स, पृष्ठभूमि सेवा)
लिंक्स
- LRUS - जब तेज़ क्षमता आपके तंत्र को बेहतर बनाती है - स्थिर स्मृति पर साथी लेख
- पार्ट 2: नयी लाइब्रेरी बनाना - पूरा कार्यान्वयन
- कार्य - मेलसीएस पैटर्न पर लाइन्स
- तंत्र. थ्रेडिंग - निर्माता-cadeser पुरातन हम उपयोग करते हैं
- आईएससीसी दस्तावेज़Comment KASP.ENT का निर्माण कैश में