نحوه فراخوانی متدهای غیر همزمان از متدهای همزمان در C#
![](https://media.hapigan.com/avatars/3080afdd90724629854cefe03bef62ef.webp)
در زبان C#، متدهای غیرهمزمان (async) به گونهای طراحی شدهاند که بتوانند بدون مسدود کردن ترد (Thread) اصلی، عملیاتهای زمان بر را انجام دهند. اما در برخی موارد، ممکن است نیاز داشته باشید که یک متد غیر همزمان را از یک متد همزمان فراخوانی کنید. این موضوع چالشهایی را به همراه دارد، به خصوص در برنامههای ASP.NET و WinForms که به زمینه همزمانی (Synchronization Context) وابستهاند.
استفاده از Task.WaitAndUnwrapException:
اگر متد غیرهمزمان شما نیازی به همگامسازی با کانتکست همزمانی ندارد، میتوانید از روش زیر کنید:
var task = MyAsyncMethod();
var result = task.WaitAndUnwrapException();
استفاده از AsyncContext.RunTask:
در صورتی که متد غیرهمزمان شما نیاز به همگامسازی با کانتکست همزمانی دارد، میتوانید از روش زیر استفاده کنید که از مسدود شدن جلوگیری می کند:
var result = AsyncContext.RunTask(MyAsyncMethod).Result;
اجرای متد غیرهمزمان در Thread Pool:
گر متد غیرهمزمان شما به دسترسی به UI یا زمینه ASP.NET نیاز دارد، میتوانید از روش زیر استفاده کنید. اما توجه داشته باشید که این روش ممکن است باعث ایجاد شرایط نامناسبی در محیطهای وب شود، زیرا میتواند منابع ترد را محدود کند.
var task = Task.Run(async () => await MyAsyncMethod());
var result = task.WaitAndUnwrapException();
استفاده از AsyncHelper:
کلاس AsyncHelper
که میتوانید آن را به روش زیر پیادهسازی کنید، به شما اجازه میدهد تا متدهای غیرهمزمان را به صورت همزمان اجرا کنید:
internal static class AsyncHelper
{
private static readonly TaskFactory _myTaskFactory = new
TaskFactory(CancellationToken.None,
TaskCreationOptions.None,
TaskContinuationOptions.None,
TaskScheduler.Default);
public static TResult RunSync<TResult>(Func<Task<TResult>> func)
{
return AsyncHelper._myTaskFactory
.StartNew<Task<TResult>>(func)
.Unwrap<TResult>()
.GetAwaiter()
.GetResult();
}
public static void RunSync(Func<Task> func)
{
AsyncHelper._myTaskFactory
.StartNew<Task>(func)
.Unwrap()
.GetAwaiter()
.GetResult();
}
}
روش فراخوانی:
AsyncHelper.RunSync<TUser>(() => manager.FindByIdAsync(10));
ملاحظات
- خطرات احتمالی: استفاده نادرست از این تکنیکها ممکن است به مشکلاتی مانند Deadlock منجر شود. بنابراین، توصیه میشود که این روشها را با احتیاط به کار ببرید و از استفاده از
ConfigureAwait(false)
در متدهای غیرهمزمان خود غافل نشوید. - محیطهای مخصوص: در محیطهای ASP.NET Core، به دلیل نبود کانتکست همزمانی خاص، بعضی از این روشها به درستی کار میکنند اما در ASP.NET قدیمیتر ممکن است باعث مشکلاتی شوند.