C#中的同步任务执行

时间:2015-11-27 20:19:57

标签: c# c#-4.0 async-await task-parallel-library

我在Singleton类中有一个方法,它将从不同的线程调用。但我需要逐个执行它们。喜欢

将从多个线程调用ImageUtil.Instance.LoadImage(imageID)方法。但我想逐个加载图片。因此,一次只会加载一个图像。

public class ImageUtil
{
    #region Singleton Implementation
    private ImageUtil()
    {
        taskList = new List<Task<object>>();
    }

    public static ImageUtil Instance { get { return Nested.instance; } }

    private class Nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as before field init
        static Nested()
        {
        }

        internal static readonly ImageUtil instance = new ImageUtil();
    }

    #endregion

    Queue<Task<Object>> taskList;
    bool isProcessing;
    public async Task<Object> LoadImage(String imageID)
    {
        //Here what I need to put to execute "return await LoadImageInternal(imageID);"
        //one by one. So that if one image is loading and mean time some other thread
        //calls this method then the last thread have to wait until current loading finish.

    }
    private async Task<Object> LoadImageInternal(String imageID)
    {
        //Business Logic for image retrieval.
    }
}

3 个答案:

答案 0 :(得分:6)

SemaphoreSlim有一个WaitAsync方法,允许您异步执行关键部分:

private readonly SemaphoreSlim loadSemaphore = new SemaphoreSlim(1, 1);

public async Task<Object> LoadImage(String imageID)
{
    await loadSemaphore.WaitAsync();

    try
    {
        return await LoadImageInternal(imageID);
    }
    finally
    {
        loadSemaphore.Release();
    }
}

此模式显示在Stephen Toub's article

答案 1 :(得分:0)

List<Task<Object>> taskList;
private static readonly object _syncLock = new object();
public Task<Object> LoadImage(String imageID)
{
    return Task<Object>.Factory.StartNew(() =>
    {
        lock (_syncLock)
        {
            return LoadImageInternal(imageID).Result;
        }
    });
}
private async Task<Object> LoadImageInternal(String imageID)
{
    //Business Logic for image retrieval.
}

那应该完成你要求的,但我个人会用一个长期运行的任务和某种Queue来解决这个问题。长时间运行的任务将永远循环并检查队列中的新项目,然后一次执行一个,这将防止大量不必要的线程上下文切换。

答案 2 :(得分:0)

//This is how you can implement it using yield return to return one image at a time
public IEnumerable<Task<string>> GetPerItemAsync(IEnumerable<string> images)
{
    foreach (var image in images)
    {
       yield return LoadImage(image);
    }
 }

 public static Task<string> LoadImage(string image)
 {
     var result = image.Trim(); // Some complex business logic on the image, NOT

     return new Task<string>(() => result);
  }

  //Call your method in you client
  //First, get your images from the data source
  var listOfimages = Context.Images.ToList();

  //Get results
  var result = GetPerItemAsync(listOfimages).FirstOrDefault();