আমি এই প্রশ্নটি সত্যিই পছন্দ করি:
আগুন নেওয়ার সহজ উপায় এবং সি # তে পদ্ধতিটি ভুলে যাবেন?
আমি কেবল জানতে চাই যে এখন সি # ৪.০ এ আমাদের সমান্তরাল এক্সটেনশান রয়েছে কি সমান্তরাল লিংকের সাথে ফায়ার এবং ভুলে যাওয়ার আরও ভাল ক্লিনার কোন উপায় আছে?
আমি এই প্রশ্নটি সত্যিই পছন্দ করি:
আগুন নেওয়ার সহজ উপায় এবং সি # তে পদ্ধতিটি ভুলে যাবেন?
আমি কেবল জানতে চাই যে এখন সি # ৪.০ এ আমাদের সমান্তরাল এক্সটেনশান রয়েছে কি সমান্তরাল লিংকের সাথে ফায়ার এবং ভুলে যাওয়ার আরও ভাল ক্লিনার কোন উপায় আছে?
উত্তর:
৪.০ এর কোনও উত্তর নয়, তবে এটি লক্ষণীয় .. নেট ৪.৫ আপনি এটিকে আরও সহজ করে তুলতে পারেন:
#pragma warning disable 4014
Task.Run(() =>
{
MyFireAndForgetMethod();
}).ConfigureAwait(false);
#pragma warning restore 4014
প্রগমা হ'ল সতর্কতাটি অক্ষম করা যা আপনাকে বলে যে আপনি এই কার্যটিকে আগুন হিসাবে চালাচ্ছেন এবং ভুলে যাচ্ছেন।
যদি কোঁকড়া ধনুর্বন্ধনী এর ভিতরে পদ্ধতিটি একটি কার্য ফেরত দেয়:
#pragma warning disable 4014
Task.Run(async () =>
{
await MyFireAndForgetMethod();
}).ConfigureAwait(false);
#pragma warning restore 4014
আসুন এটি ভেঙে দিন:
টাস্ক.রুন একটি টাস্ক ফেরত দেয়, যা একটি সংকলক সতর্কতা উত্পন্ন করে (CS4014 সতর্ক করে) উল্লেখ করে যে এই কোডটি পটভূমিতে চালিত হবে - এটি আপনি যা চেয়েছিলেন ঠিক তাই, তাই আমরা সতর্কতা 4040 অক্ষম করে দিয়েছি।
ডিফল্টরূপে, টাস্কগুলি "মার্শালটিকে মূল মূল থ্রেডে ফিরে যেতে" চেষ্টা করে যার অর্থ এই টাস্কটি পটভূমিতে চলবে, তারপরে এটি শুরু হওয়া থ্রেডে ফিরে আসার চেষ্টা করবে। আসল থ্রেডটি শেষ হওয়ার পরে প্রায়শই গুলি চালান এবং ভুলে যান এটি থ্রেডঅবর্টেক্সপশন নিক্ষেপ করবে। বেশিরভাগ ক্ষেত্রে এটি নিরীহ - এটি কেবল আপনাকে বলছে, আমি আবার যোগদানের চেষ্টা করেছি, আমি ব্যর্থ হয়েছি, তবে আপনি যাইহোক যত্ন নেন না। তবে প্রোডাকশনে আপনার লগগুলিতে বা স্থানীয় দেবের ডিবাগারে থ্রেডআবার্টএক্সপ্যাজেসন পাওয়া এখনও খানিকটা গোলমাল।.ConfigureAwait(false)
পরিপাটি থাকা এবং স্পষ্টভাবে বলতে চাওয়ার এক উপায়, এটি ব্যাকগ্রাউন্ডে চালান, এবং এটিই।
যেহেতু এটি শব্দযুক্ত, বিশেষত কুৎসিত প্রগমা, আমি এটির জন্য একটি লাইব্রেরি পদ্ধতি ব্যবহার করি:
public static class TaskHelper
{
/// <summary>
/// Runs a TPL Task fire-and-forget style, the right way - in the
/// background, separate from the current thread, with no risk
/// of it trying to rejoin the current thread.
/// </summary>
public static void RunBg(Func<Task> fn)
{
Task.Run(fn).ConfigureAwait(false);
}
/// <summary>
/// Runs a task fire-and-forget style and notifies the TPL that this
/// will not need a Thread to resume on for a long time, or that there
/// are multiple gaps in thread use that may be long.
/// Use for example when talking to a slow webservice.
/// </summary>
public static void RunBgLong(Func<Task> fn)
{
Task.Factory.StartNew(fn, TaskCreationOptions.LongRunning)
.ConfigureAwait(false);
}
}
ব্যবহার:
TaskHelper.RunBg(async () =>
{
await doSomethingAsync();
}
ConfigureAwait(false)
উপর Task.Run
যখন আপনি না await
কাজ। ফাংশনটির উদ্দেশ্য এর নামে: " অপেক্ষা করুন কনফিগার করুন "। আপনি যদি await
কাজটি না করেন তবে আপনি একটি ধারাবাহিকতা নিবন্ধভুক্ত করবেন না এবং আপনি যেমন বলছেন তেমন কোনও কাজের জন্য "মূল থ্রেডে মার্শাল" করার কোনও কোড নেই। চূড়ান্তকরণকারী থ্রেডে পুনরায় উত্থাপিত হওয়ার পরে আরও বড় ঝুঁকি হ'ল, যা এই উত্তরটিও সম্বোধন করে না।
#Disable Warning BC42358
সঙ্গে Task
বর্গ হ্যাঁ, কিন্তু PLINQ সংগ্রহের উপর অনুসন্ধান জন্য সত্যিই হয়।
নীচের মতো কিছু এটি টাস্কের সাহায্যে করবে।
Task.Factory.StartNew(() => FireAway());
অথবা এমনকি...
Task.Factory.StartNew(FireAway);
বা ...
new Task(FireAway).Start();
কোথায় FireAway
আছে
public static void FireAway()
{
// Blah...
}
সুতরাং শ্রেণি এবং পদ্ধতির নামের স্বল্পতার কারণে এই আপনি থ্রেডপুল সংস্করণটিকে ছয় থেকে উনিশ বর্ণচিহ্নের মধ্যে হারিয়েছেন যা আপনি চয়ন করেছেন তার উপর নির্ভর করে :)
ThreadPool.QueueUserWorkItem(o => FireAway());
fire and forget in ASP.NET WebForms and windows.close()
?
এই প্রশ্নের অগ্রণী উত্তর নিয়ে আমার কয়েকটি সমস্যা রয়েছে।
প্রথমত, একটি সত্য আগুন এবং ভুলে যাওয়া পরিস্থিতিতে, আপনি সম্ভবত await
টাস্কটি করবেন না , তাই সংযোজন করা অযথা ConfigureAwait(false)
। আপনি যদি await
মানটি না দিয়ে দেনConfigureAwait
, তবে সম্ভবত এটির কোনও প্রভাব থাকতে পারে না।
দ্বিতীয়ত, যখন টাস্কটি একটি ব্যতিক্রম পূর্ণ করে তখন কী হয় তা সম্পর্কে আপনার সচেতন হওয়া দরকার। @ অ্যাড-মিলার প্রস্তাবিত সহজ সমাধানটি বিবেচনা করুন:
Task.Factory.StartNew(SomeMethod); // .NET 4.0
Task.Run(SomeMethod); // .NET 4.5
এটি একটি বিপত্তির পরিচয় দেয়: যদি একটি অপরিবর্তিত ব্যতিক্রম এড়ায় SomeMethod()
, তবে সে ব্যতিক্রম কখনও পর্যবেক্ষণ করা হবে না এবং আপনার অ্যাপ্লিকেশনটি ক্র্যাশ করে 1 টি চূড়ান্তকরণকারী থ্রেডে পুনর্বিবেচনা করা হতে পারে। অতএব, ফলস্বরূপ যে কোনও ব্যতিক্রম পরিলক্ষিত হচ্ছে তা নিশ্চিত করতে আমি কোনও সহায়ক পদ্ধতি ব্যবহার করার পরামর্শ দেব recommend
আপনি এই জাতীয় কিছু লিখতে পারেন:
public static class Blindly
{
private static readonly Action<Task> DefaultErrorContinuation =
t =>
{
try { t.Wait(); }
catch {}
};
public static void Run(Action action, Action<Exception> handler = null)
{
if (action == null)
throw new ArgumentNullException(nameof(action));
var task = Task.Run(action); // Adapt as necessary for .NET 4.0.
if (handler == null)
{
task.ContinueWith(
DefaultErrorContinuation,
TaskContinuationOptions.ExecuteSynchronously |
TaskContinuationOptions.OnlyOnFaulted);
}
else
{
task.ContinueWith(
t => handler(t.Exception.GetBaseException()),
TaskContinuationOptions.ExecuteSynchronously |
TaskContinuationOptions.OnlyOnFaulted);
}
}
}
এই বাস্তবায়নটির ন্যূনতম ওভারহেড থাকা উচিত: যদি কাজটি সফলভাবে শেষ না হয় তবে ধারাবাহিকতা চালিত হয় এবং এটি সমলয়ভাবে আহ্বান করা উচিত (মূল কাজ থেকে পৃথকভাবে নির্ধারিত হওয়ার বিপরীতে)। "অলস" ক্ষেত্রে, আপনি এমনকি ধারাবাহিক প্রতিনিধিদের জন্য বরাদ্দও ব্যয় করতে পারবেন না।
একটি অ্যাসিনক্রোনাস অপারেশন চালু করা তুচ্ছ হয়ে যায়:
Blindly.Run(SomeMethod); // Ignore error
Blindly.Run(SomeMethod, e => Log.Warn("Whoops", e)); // Log error
১। নেট 4.0.০ এ ডিফল্ট আচরণ ছিল। .NET 4.5-এ, ডিফল্ট আচরণটি এমনভাবে পরিবর্তন করা হয়েছিল যে অননक्षित সংরক্ষিত ব্যতিক্রমগুলি চূড়ান্তকরণকারী থ্রেডে পুনরায় আরম্ভ করা হবে না (যদিও আপনি এখনও এগুলি টাস্কশেডুলারের অনাবৃত টাস্ক এক্সপশন ইভেন্টের মাধ্যমে পর্যবেক্ষণ করতে পারেন)। যাইহোক, ডিফল্ট কনফিগারেশন ওভাররাইড করা যেতে পারে এবং আপনার অ্যাপ্লিকেশনটি .NET 4.5 প্রয়োজন থাকলেও, আপনার ধরে নেওয়া উচিত নয় যে অনাবৃত টাস্ক ব্যতিক্রমগুলি নিরীহ হবে।
ContinueWith
বাতিল হওয়ার কারণে অনুরোধ করা হয়, তবে পূর্বসূরির ব্যতিক্রম সম্পত্তি নাল হবে এবং একটি নাল রেফারেন্স ব্যতিক্রম নিক্ষেপ করা হবে। টাস কন্টিনিউশন অপশনে সেট করা OnlyOnFaulted
নাল চেকের প্রয়োজনীয়তা দূর করবে বা এটি ব্যবহারের আগে ব্যতিক্রমটি শূন্য রয়েছে কিনা তা পরীক্ষা করবে।
Task
প্রয়োগের বিশদ হয়ে যায়।
Task
" এইরকম নয় "আমি কোনও ব্যাকগ্রাউন্ড অপারেশন শুরু করার সহজ উপায় চাই, তার ফলাফলটি কখনই পর্যবেক্ষণ করি না, এবং কোন পদ্ধতিটি ব্যবহার করা হয় তা আমি যত্ন করি না don't এটা করতে। " সেই ভিত্তিতে আমি আমার উত্তরের পিছনে দাঁড়িয়ে আছি যে প্রশ্ন জিজ্ঞাসা করা হয়েছিল ।
fire and forget
মধ্যে ASP.NET ওয়েবফর্মগুলি এবং windows.close()
?
মাইক স্ট্রোবেলের উত্তরের সাথে ঘটতে পারে এমন কিছু সমস্যা সমাধান করার জন্য:
আপনি যদি সেই কাজে ব্যবহার করে var task = Task.Run(action)
এবং ধারাবাহিকতা নির্ধারণ করেন, তবে আপনি Task
ব্যতিক্রম হ্যান্ডলার ধারাবাহিকতাটি নির্ধারণ করার আগে আপনি কিছু ব্যতিক্রম ছুঁড়ে ফেলার ঝুঁকিতে পড়বেন Task
। সুতরাং, নীচের শ্রেণিগুলি এই ঝুঁকি থেকে মুক্ত হওয়া উচিত:
using System;
using System.Threading.Tasks;
namespace MyNameSpace
{
public sealed class AsyncManager : IAsyncManager
{
private Action<Task> DefaultExeptionHandler = t =>
{
try { t.Wait(); }
catch { /* Swallow the exception */ }
};
public Task Run(Action action, Action<Exception> exceptionHandler = null)
{
if (action == null) { throw new ArgumentNullException(nameof(action)); }
var task = new Task(action);
Action<Task> handler = exceptionHandler != null ?
new Action<Task>(t => exceptionHandler(t.Exception.GetBaseException())) :
DefaultExeptionHandler;
var continuation = task.ContinueWith(handler,
TaskContinuationOptions.ExecuteSynchronously
| TaskContinuationOptions.OnlyOnFaulted);
task.Start();
return continuation;
}
}
}
এখানে, task
সরাসরি চালানো হয় না, পরিবর্তে এটি তৈরি করা হয়, একটি ধারাবাহিকতা বরাদ্দ করা হয়, এবং কেবল তখনই ধারাবাহিকতা নির্ধারণের আগে কার্য সম্পাদন (বা কিছু ব্যতিক্রম ছুঁড়ে দেওয়া) সম্পন্ন করার ঝুঁকি দূর করার জন্য টাস্কটি চালানো হয়।
এখানে Run
পদ্ধতিটি ধারাবাহিকতাটি ফিরিয়ে দেয় Task
তাই আমি কার্যকর হয়ে গেছে কিনা তা নিশ্চিত করে ইউনিট পরীক্ষা লিখতে সক্ষম হয়েছি। যদিও আপনি আপনার ব্যবহারের ক্ষেত্রে এটি নিরাপদে উপেক্ষা করতে পারেন।