শীর্ষে ভোট দেওয়া উত্তরের উপর ভিত্তি করে এখানে একটি পরিপূর্ণ কাজ উদাহরণ, যা:
int timeout = 1000;
var task = SomeOperationAsync();
if (await Task.WhenAny(task, Task.Delay(timeout)) == task) {
// task completed within timeout
} else {
// timeout logic
}
এই উত্তরের বাস্তবায়নের মূল সুবিধাটি হ'ল জেনেরিকগুলি যুক্ত করা হয়েছে, সুতরাং ফাংশন (বা কার্য) কোনও মান ফিরিয়ে দিতে পারে। এর অর্থ হ'ল যে কোনও বিদ্যমান ফাংশন একটি টাইমআউট ফাংশনে আবৃত হতে পারে, যেমন:
আগে:
int x = MyFunc();
পরে:
// Throws a TimeoutException if MyFunc takes more than 1 second
int x = TimeoutAfter(MyFunc, TimeSpan.FromSeconds(1));
এই কোডটি .NET 4.5 প্রয়োজন।
using System;
using System.Threading;
using System.Threading.Tasks;
namespace TaskTimeout
{
public static class Program
{
/// <summary>
/// Demo of how to wrap any function in a timeout.
/// </summary>
private static void Main(string[] args)
{
// Version without timeout.
int a = MyFunc();
Console.Write("Result: {0}\n", a);
// Version with timeout.
int b = TimeoutAfter(() => { return MyFunc(); },TimeSpan.FromSeconds(1));
Console.Write("Result: {0}\n", b);
// Version with timeout (short version that uses method groups).
int c = TimeoutAfter(MyFunc, TimeSpan.FromSeconds(1));
Console.Write("Result: {0}\n", c);
// Version that lets you see what happens when a timeout occurs.
try
{
int d = TimeoutAfter(
() =>
{
Thread.Sleep(TimeSpan.FromSeconds(123));
return 42;
},
TimeSpan.FromSeconds(1));
Console.Write("Result: {0}\n", d);
}
catch (TimeoutException e)
{
Console.Write("Exception: {0}\n", e.Message);
}
// Version that works on tasks.
var task = Task.Run(() =>
{
Thread.Sleep(TimeSpan.FromSeconds(1));
return 42;
});
// To use async/await, add "await" and remove "GetAwaiter().GetResult()".
var result = task.TimeoutAfterAsync(TimeSpan.FromSeconds(2)).
GetAwaiter().GetResult();
Console.Write("Result: {0}\n", result);
Console.Write("[any key to exit]");
Console.ReadKey();
}
public static int MyFunc()
{
return 42;
}
public static TResult TimeoutAfter<TResult>(
this Func<TResult> func, TimeSpan timeout)
{
var task = Task.Run(func);
return TimeoutAfterAsync(task, timeout).GetAwaiter().GetResult();
}
private static async Task<TResult> TimeoutAfterAsync<TResult>(
this Task<TResult> task, TimeSpan timeout)
{
var result = await Task.WhenAny(task, Task.Delay(timeout));
if (result == task)
{
// Task completed within timeout.
return task.GetAwaiter().GetResult();
}
else
{
// Task timed out.
throw new TimeoutException();
}
}
}
}
আদেশ সহকারে
এই উত্তরটি দেওয়ার পরে, এটি সাধারণত হয় না সাধারণ ক্রিয়াকলাপের সময় আপনার কোডে ব্যতিক্রম ছড়িয়ে দেওয়া ভাল অভ্যাস , যদি না আপনার একেবারে করতে হয়:
- প্রতিবার ব্যতিক্রম নিক্ষেপ করা হলে এটি একটি অত্যন্ত ভারী ওজনের অপারেশন,
- ব্যতিক্রমগুলি যদি শক্ত লুপে থাকে তবে ব্যতিক্রমগুলি 100 বা তার বেশি ফ্যাক্টর দ্বারা আপনার কোডকে ধীর করতে পারে।
কেবলমাত্র এই কোডটি ব্যবহার করুন যদি আপনি কল করে ফাংশনটি একেবারে পরিবর্তন করতে না পারেন তবে নির্দিষ্ট সময়ের পরে এটি বার হয়ে যায় TimeSpan
।
এই উত্তরটি কেবলমাত্র তৃতীয় পক্ষের লাইব্রেরি গ্রন্থাগারগুলির সাথে ডিল করার সময় প্রযোজ্য যা আপনি কেবল টাইমআউট প্যারামিটার অন্তর্ভুক্ত করতে রিফ্যাক্টর করতে পারবেন না।
কিভাবে শক্ত কোড লিখতে হয়
আপনি যদি দৃust় কোডটি লিখতে চান তবে সাধারণ নিয়মটি হ'ল:
প্রতিটি একক ক্রিয়াকলাপ যা সম্ভাব্যভাবে অনির্দিষ্টকালের জন্য অবরুদ্ধ করতে পারে, তার একটি সময়সীমা থাকতে হবে।
আপনি যদি এই নিয়মটি পর্যবেক্ষণ না করেন তবে আপনার কোডটি শেষ পর্যন্ত কোনও ক্রিয়াকলাপকে আঘাত করবে যা কোনও কারণে ব্যর্থ হয়, তবে এটি অনির্দিষ্টকালের জন্য ব্লক হয়ে যাবে এবং আপনার অ্যাপ্লিকেশনটি স্থায়ীভাবে স্থায়ীভাবে স্থগিত হয়ে গেছে।
যদি কিছু সময়ের পরে যুক্তিসঙ্গত সময়সীমা থাকে তবে আপনার অ্যাপ্লিকেশনটি কিছু চরম পরিমাণে (যেমন 30 সেকেন্ড) স্থির থাকবে তবে তা হয় ত্রুটি প্রদর্শন করবে এবং এর আনন্দময় পথে চালিয়ে যাবে, বা আবার চেষ্টা করবে।