আমি এটির জন্য টিপিএল ডেটাফ্লো ব্যবহার করব (যেহেতু আপনি .NET 4.5 ব্যবহার করছেন এবং এটি Taskঅভ্যন্তরীণভাবে ব্যবহার করে)। ActionBlock<TInput>এটি ক্রিয়া প্রক্রিয়াজাত হওয়ার পরে এবং উপযুক্ত সময়ের জন্য অপেক্ষা করার পরে কোন আইটেম নিজের কাছে পোস্ট করে আপনি সহজেই এটি তৈরি করতে পারেন ।
প্রথমে এমন একটি কারখানা তৈরি করুন যা আপনার কখনও শেষ না হওয়া কাজটি তৈরি করবে:
ITargetBlock<DateTimeOffset> CreateNeverEndingTask(
Action<DateTimeOffset> action, CancellationToken cancellationToken)
{
if (action == null) throw new ArgumentNullException("action");
ActionBlock<DateTimeOffset> block = null;
block = new ActionBlock<DateTimeOffset>(async now => {
action(now);
await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken).
ConfigureAwait(false);
block.Post(DateTimeOffset.Now);
}, new ExecutionDataflowBlockOptions {
CancellationToken = cancellationToken
});
return block;
}
আমি ActionBlock<TInput>একটি DateTimeOffsetকাঠামো নিতে বেছে নিয়েছি ; আপনাকে একটি প্রকারের প্যারামিটারটি পাস করতে হবে এবং এটি কিছু কার্যকর অবস্থাও পাস করতে পারে (আপনি চাইলে রাষ্ট্রের প্রকৃতি পরিবর্তন করতে পারেন)।
এছাড়াও, নোট করুন যে ActionBlock<TInput>ডিফল্টরূপে একবারে কেবলমাত্র একটি আইটেম প্রসেস হয় , সুতরাং আপনি গ্যারান্টিযুক্ত যে কেবলমাত্র একটি ক্রিয়া প্রক্রিয়াজাত করা হবে (অর্থাত্ যখন এটি এক্সটেনশন পদ্ধতিটি নিজেই ফিরে আসে তখন আপনাকে পুনরায় পুনঃস্থাপনের মুখোমুখি হতে হবে না )।Post
আমি CancellationTokenকাঠামোটি কনস্ট্রাক্টর ActionBlock<TInput>এবং Task.Delayপদ্ধতি কল উভয়কেই দিয়েছি ; যদি প্রক্রিয়াটি বাতিল হয় তবে বাতিলকরণটি প্রথম সম্ভাব্য সুযোগে হবে।
সেখান থেকে কার্যকর করা ITargetBlock<DateTimeoffset>ইন্টারফেসটি সংরক্ষণ করার জন্য আপনার কোডটির একটি সহজ রিফ্যাকচারিং ActionBlock<TInput>(এটি হ'ল উচ্চ-স্তরের বিমূর্ততা যা উপভোক্তাদের ব্লকগুলি উপস্থাপন করে এবং আপনি Postএক্সটেনশন পদ্ধতিতে একটি কলের মাধ্যমে গ্রাহককে ট্রিগার করতে সক্ষম হতে চান ):
CancellationTokenSource wtoken;
ActionBlock<DateTimeOffset> task;
আপনার StartWorkপদ্ধতি:
void StartWork()
{
wtoken = new CancellationTokenSource();
task = CreateNeverEndingTask(now => DoWork(), wtoken.Token);
task.Post(DateTimeOffset.Now);
}
এবং তারপরে আপনার StopWorkপদ্ধতি:
void StopWork()
{
using (wtoken)
{
wtoken.Cancel();
}
wtoken = null;
task = null;
}
আপনি এখানে টিপিএল ডেটাফ্লো ব্যবহার করতে চান কেন? কয়েকটি কারণ:
উদ্বেগ বিচ্ছেদ
CreateNeverEndingTaskপদ্ধতি এখন একটি কারখানা যে আপনার "পরিষেবা" তাই কথা বলতে সৃষ্টি করে। কখন এটি শুরু হয় এবং থামবে আপনি নিয়ন্ত্রণ করেন এবং এটি সম্পূর্ণ স্বনির্ভর। আপনার কোডের অন্যান্য দিকগুলির সাথে আপনাকে টাইমারের স্টেট কন্ট্রোলটি অন্তর্বর্তী করতে হবে না। আপনি কেবল এই ব্লকটি তৈরি করেন, এটি শুরু করুন এবং আপনার হয়ে গেলে এটি বন্ধ করুন।
থ্রেড / টাস্ক / রিসোর্সের আরও দক্ষ ব্যবহার
টিপিএল ডেটা প্রবাহে ব্লকগুলির জন্য ডিফল্ট সময়সূচী এটির জন্য একই Task, যা থ্রেড পুল। ActionBlock<TInput>আপনার ক্রিয়াকলাপটি প্রক্রিয়াকরণ করার জন্য, পাশাপাশি কল করার Task.Delayমাধ্যমে আপনি যখন কিছুই করছেন না তখন আপনি যে থ্রেডটি ব্যবহার করছেন সেটি নিয়ন্ত্রণ পেয়ে যাচ্ছেন। মঞ্জুর, আপনি যখন নতুনত্বের Taskধারাবাহিকতাটি প্রসেস করবেন তখন এটি কিছুটা ওভারহেডের দিকে নিয়ে যায় , তবে এটি ছোট হওয়া উচিত, বিবেচনা করে আপনি এটিকে কোনও টান লুপে প্রসেস করছেন না (আপনি অনুরোধের মধ্যে দশ সেকেন্ড অপেক্ষা করছেন)।
যদি DoWorkফাংশনটি প্রকৃতপক্ষে অপেক্ষারত করা যায় (যেমন, এটির সাথে এটি প্রত্যাবর্তন করে Task), তবে আপনি উপরের কারখানার পদ্ধতিটি টুইটার করে আরও সম্ভবত এটি অনুকূল করতে পারেন , এর মতো Func<DateTimeOffset, CancellationToken, Task>পরিবর্তে Action<DateTimeOffset>:
ITargetBlock<DateTimeOffset> CreateNeverEndingTask(
Func<DateTimeOffset, CancellationToken, Task> action,
CancellationToken cancellationToken)
{
if (action == null) throw new ArgumentNullException("action");
ActionBlock<DateTimeOffset> block = null;
block = new ActionBlock<DateTimeOffset>(async now => {
await action(now, cancellationToken).
ConfigureAwait(false);
await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken).
ConfigureAwait(false);
block.Post(DateTimeOffset.Now);
}, new ExecutionDataflowBlockOptions {
CancellationToken = cancellationToken
});
return block;
}
অবশ্যই, এটি CancellationTokenআপনার পদ্ধতির মাধ্যমে বুনন করা ভাল অনুশীলন হবে (যদি এটি কোনও গ্রহণ করে), যা এখানে করা হয়।
তার মানে আপনার তখন DoWorkAsyncনিম্নলিখিত স্বাক্ষর সহ একটি পদ্ধতি থাকবে :
Task DoWorkAsync(CancellationToken cancellationToken);
আপনাকে পরিবর্তিত করতে হবে (কেবলমাত্র সামান্য, এবং আপনি উদ্বেগের বিচ্ছেদ থেকে এখানে রক্তপাত করছেন না) StartWorkপদ্ধতিটিতে পাস করা নতুন স্বাক্ষরের জন্য অ্যাকাউন্টটি CreateNeverEndingTaskপদ্ধতি, যেমন:
void StartWork()
{
wtoken = new CancellationTokenSource();
task = CreateNeverEndingTask((now, ct) => DoWorkAsync(ct), wtoken.Token);
task.Post(DateTimeOffset.Now, wtoken.Token);
}