簡體   English   中英

在C#中使用Func with Task

[英]Using Func with Task in C#

我在嘗試理解Func在C#中的確切運作方式時遇到了一些問題,盡管我已經閱讀了一些關於它的好博客。

我有以下場景:我正在構建一個小型計費系統,它使用Azure Service Bus隊列來處理賬單。 用戶可以初始化兩個進程:

  1. 創建一個日記帳,以便在之前檢查交易是否正確
  2. 為客戶創建實際發票

為此,我提出了一種初始化計費任務(包含N個賬單)的通用方法,該方法采用bool參數來判斷是否需要創建日記本或實際賬單。 在這個方法中,我正在運行以下檢查:

if (isDayBookProcessing)
{
    // Daybook processing code here   
}
else
{
    // Run queue process async
    StartQueueProcess(queueName, billingTaskId, numOfItemsEnqueued);
}

然后我得到了一個通用的“StartQueueProcess”方法,它在它自己的Task運行,如下所示:

private void StartQueueProcess(string queueName, int billingTaskId, int numOfItemsEnqueued)
{
    Task.Factory.StartNew(() => _factory.AzureFactory.ServiceBus.ProcessBillingQueue(queueName, billingTaskId, numOfItemsEnqueued));
}

如您所見, StartQueueProcess方法在我的ServiceBus類上運行ProcessBillingQueue方法,這意味着它無法運行ProcessDaybookQueue

我最初想的是只使用Func<string, int, int, bool>並使StartQueueProcess方法返回一個bool(因為Func需要返回一些東西),使它看起來像這樣:

if (isDayBookProcessing)
{
    // Daybook processing code here 
    StartQueueProcess(_factory.AzureFactory.ServiceBus.ProcessDaybookQueue(queueName, billingTaskId, numOfItemsEnqueued));  
}
else
{
    // Run queue process async   
    StartQueueProcess(_factory.AzureFactory.ServiceBus.ProcessBillingQueue(queueName, billingTaskId, numOfItemsEnqueued));
}

private bool StartQueueProcess(Func<string, int, int, bool> processMethod)
{
    Task.Factory.StartNew(() => processMethod);

    return true;
}

但是,這會給出一個錯誤,告訴我Argument type 'void' is not assignable to parameter type 'System.Func<string, int, int bool>'

我的_factory.AzureFactory.ServiceBus.ProcessDaybookQueue(queueName, billingTaskId, numOfItemsEnqueued)返回void。 使它返回Func<string, int, int, bool>沒有錯誤。 但為什么呢? 我不應該能夠讓它返回我想要的東西(即無效)嗎?

任何人都可以對此有所了解嗎? :-)

你不需要一個Func ,你需要一個Action Func是您的委托具有返回值的時間。 沒有返回值時, Action適合:

private void StartQueueProcess(Action<string, int, int> processMethod)
{
    Task.Factory.StartNew(() => processMethod);
}

請注意,將異步重疊包裝為反模式 您最好在呼叫站點使用Task.Run

if (isDayBookProcessing)
{
    // Daybook processing code here 
    Task.Run(() => _factory.AzureFactory.ServiceBus.ProcessDaybookQueue(
                           queueName, 
                           billingTaskId, 
                           numOfItemsEnqueued));  
}
else
{
    // Run queue process async   
    Task.Run(() => _factory.AzureFactory.ServiceBus.ProcessBillingQueue(
                           queueName,
                           billingTaskId, 
                           numOfItemsEnqueued));
} 

雖然我看到你正在調用相同的方法,所以我認為不需要if-else

我看到兩個不同的問題:1。我擔心Task.Factory.StartNew(() => processMethod)不會按預期執行。 它不會執行processMethod 2. StartQueueProcess被定義為接受具有三個參數的Func <>函數。 它沒有提到參數本身。 你有責任為這個lambda提供一些參數。

你為什么假設你需要在這里使用Func<> 你不必。 你的StartQueueProcess可以像這樣:

private bool StartQueueProcess(
     string param1, 
     int param2, 
     int param3, 
     Action<string, int, int> processMethod)
{
    Task.Factory.StartNew(() => processMethod(param1, param2, param3));
}

例如,這個StartNew重載將很樂意接受任何Action參數)。

而且,在這個特殊情況下,我認為根本不需要聲明一個新函數。 一個簡單的.StartNew調用可能會很好(盡管它很接近):

if (isDayBookProcessing)
{
    // Daybook processing code here 
    Task.Factory.StartNew(() =>  _factory
        .AzureFactory
        .ServiceBus
        .ProcessDaybookQueue(queueName, billingTaskId, numOfItemsEnqueued));  
}
else
{
    // Run queue process async   
    Task.Factory.StartNew(() => _factory
        .AzureFactory
        .ServiceBus
        .ProcessBillingQueue(queueName, billingTaskId, numOfItemsEnqueued));
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM