-4

I am having Parallel For loop for following statements but I want to use async task not Parallel. Any idea how can i use async task on same statements? I don't need fully working code but just an idea about how to replace async task with Parallel. Happy coding

Parallel.For(0, allRequests.Count(), i =>
{
    var rand = new Random();
    var token = allTokens.ElementAt(rand.Next(allTokens.Count()));
    var accessKey = token.AccessKey;
    var secretKey = token.SecretKey;
    using (var ctx = new db_mytestdb())
    {
        var firstRequest = allRequests[i];
        Console.WriteLine("Started scan for: " + firstRequest.SearchedUser.EbayUsername + " and using token: " + allTokens[i % allTokens.Count].TokenName);
        var bulkScannedItems = new ConcurrentBag<BulkScannedItems>();
        var userPreferences = ctx.UserPreferences.FirstOrDefault(x => x.UserId == firstRequest.UserId);
        var userBrekEven = userPreferences.BreakEven;

        var intoPast = DateTime.Now.Subtract(TimeSpan.FromDays(firstRequest.Range));

        var filteredProducts = ctx.EbayUserTransactions.Where(x => x.SearchedUserID == firstRequest.SearchedUserID && x.TransactionDate >= intoPast && x.TransactionDate <= firstRequest.SearchedUser.LastUpdatedAt)
            .ToList()
            .GroupBy(x => x.ItemID).Select(x => new ResultItem()
            {
                ItemID = x.Key,
                SaleNumber = x.Sum(y => y.QuantityPurchased)
            })
            .Where(x => x.SaleNumber >= firstRequest.MinSales)
            .ToList();

        var itemSpecifics = ctx.SearchedUserItems.Where(x => x.SearchedUserID == firstRequest.SearchedUserID).ToList();

        foreach (var item in itemSpecifics)
        {
            foreach (var filtered in filteredProducts)
            {
                if (item.ItemID == filtered.ItemID)
                {
                    if (item.UPC != null)
                    {
                        filtered.UPC = item.UPC;
                    }
                    else
                    {
                        filtered.UPC = "does not apply";
                    }
                    if (item.EAN != null)
                    {
                        filtered.EAN = item.EAN;
                    }
                    else
                    {
                        filtered.EAN = "does not apply";
                    }
                    if (item.MPN != null)
                    {
                        filtered.MPN = item.MPN;
                    }
                    else
                    {
                        filtered.MPN = "does not apply";
                    }

                }
            }
        }

        var bulkScanner = new BulkScannerAlgorithm();
        foreach (var dbItem in filteredProducts)
        {
            var amazonItem = bulkScanner.Found(dbItem.UPC, dbItem.ItemID, accessKey, secretKey);
            if (amazonItem.Found)
            {
                bulkScanner.InsertAmazonData(firstRequest, bulkScannedItems, userBrekEven, amazonItem);
                continue;
            }

            amazonItem = bulkScanner.Found(dbItem.EAN, dbItem.ItemID, accessKey, secretKey);
            if (amazonItem.Found)
            {
                bulkScanner.InsertAmazonData(firstRequest, bulkScannedItems, userBrekEven, amazonItem);
                continue;
            }
            amazonItem = bulkScanner.Found(dbItem.MPN, dbItem.ItemID, accessKey, secretKey);
            if (amazonItem.Found)
            {
                bulkScanner.InsertAmazonData(firstRequest, bulkScannedItems, userBrekEven, amazonItem);
                continue;
            }
        }

        List<BulkScannedItems> filteredCompleteBulk;
        if (firstRequest.IsPrimeOnly == true)
        {
            filteredCompleteBulk = bulkScannedItems.Where(x => x.CalculatedProfit >= firstRequest.MinProfit && x.IsPrime == true && x.EbayPrice >= firstRequest.minPrice && x.EbayPrice <= firstRequest.maxPrice).DistinctBy(x => x.ASIN).ToList();
        }
        else
        {
            filteredCompleteBulk = bulkScannedItems.Where(x => x.CalculatedProfit >= firstRequest.MinProfit && x.EbayPrice >= firstRequest.minPrice && x.EbayPrice <= firstRequest.maxPrice).DistinctBy(x => x.ASIN).ToList();
        }
        EFBatchOperation.For(ctx, ctx.BulkScannedItems).InsertAll(filteredCompleteBulk);
        ctx.user_scanReq_update(firstRequest.UserSellerScanRequestId);
        Console.WriteLine("Scan complete for user: " + firstRequest.SearchedUser.EbayUsername);
    }
});
poke
  • 369,085
  • 72
  • 557
  • 602
John poe
  • 17
  • 4

2 Answers2

1

Parallelism and asynchrony are both forms of concurrency, but parallelism works by dividing the problem among multiple threads, and asynchrony works by freeing up threads. So they're kind of opposites in how they work.

That said, to make the code asynchronous, you'd start from your lowest-level I/O calls, e.g., the EF ToList and presumably also whatever APIs are used in the implementation of InsertAll. Replace those with asynchronous equivalents (e.g., ToListAsync) and call them with await.

Next, you'd need to replace the Parallel.For loop with code that creates a collection of asynchronous tasks and then (asynchronously) waits for them all, something like:

var tasks = allRequests.Select(async request => { ... });
await Task.WhenAll(tasks);

That's the basic pattern for asynchronous concurrency.

If you find that you do need true parallelism (multiple threads) in addition to asynchrony, consider using TPL Dataflow.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • _but parallelism works by dividing the problem among multiple threads, and asynchrony works by freeing up threads_ - nice, this can be bolded in the answer ;) – Fabio Jul 12 '17 at 13:54
-3

A little clarification, whether you are using Parallel.For/Foreach, Tasks, or await/async, they are all using the same thing behind the scenes (albeit slightly differently). You should always pick the one that fits your problem the best.

If you want to replace the parallel.for with a method of return type Task, that is straight forward enough but you would end up waiting for this piece to be done before you continued your processing.

Async/Await is generally used when dealing with UIs and web calls, it doesn't appear to be useful here.

What is it that you are trying to accomplish? Why the need to 'replace async task with Parallel'?

The general way you would off load a method to a task would be

Task<T> task = Task<T>.Factory.StartNew(() =>
{

});

or

public Task<T> task()
{
    ..... 
}  
  • i am doing bulk data processing via api some data gets messed up when i use Parallel that's why wanted to test using async – John poe Jul 12 '17 at 12:35
  • 1
    `async`/`await` != `Task.Run()`. Tasks create new thread pool thread async/await parks the current thread so `Task.Run()` uses (at least two thread) async uses one, among other differences – Liam Jul 12 '17 at 12:35
  • *Async/Await should only be used when dealing with UIs and web calls* again not true. You should use async/await when you want to release a thread pool or UI thread. This can be from many different applications – Liam Jul 12 '17 at 12:36
  • o_O I would really advice you to read up on this. Your making many mistakes here. `Task.Run()` is the correct way to start tasks not `Task.Factory.StartNew`. [You will be missing some very important flags here](https://stackoverflow.com/a/29693430/542251) `public Task task()` is not starting a Task, it's a method that returns a `Task`, you still need to start a Task inside the method – Liam Jul 12 '17 at 12:39
  • @Liam you have a lot of comments on this question, none of which adds any information. MS best practice on MSDN directly recommends async/await for UI use. You can of course use it where ever you want, but that's the recommendation. Also, Task.Run is equivalent to calling Factory.StartNew with certain flags set. It is essentially syntax sugar. – Nicholaus Lawson Jul 12 '17 at 12:41
  • 1
    I am pointing out that much of the information in this answer is **totally wrong**. – Liam Jul 12 '17 at 12:42
  • 2
    @NicholausLawson Recommending something for one use case does not make that something not well suited for other use cases. – poke Jul 12 '17 at 12:43
  • @johnpoe if you are seeing incorrect results using parallel.for, changing it to a different type of parallel processing might not fix your problem anyway. – Nicholaus Lawson Jul 12 '17 at 12:47