نحوه فراخوانی متدهای غیر همزمان از متدهای همزمان در C#

mohsen1 ماه قبل
ارسال شده در
csharp

در زبان 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 قدیمی‌تر ممکن است باعث مشکلاتی شوند.
رای
0
ارسال نظر
مرتب سازی:
اولین نفری باشید که نظر می دهید!