如何从另一个功能完成任务?

时间:2015-11-30 13:46:57

标签: c# asynchronous

我想通过webservice从数据库中查询数据。提供的API允许发送批处理请求,以便在单个HTTP请求中发送多个请求。我想从中受益,并尝试使用异步代码和任务构建一个C#接口来使用此服务。

我的目标是实现以下目标:

#company.rb model
def self.full_hosts_hash
    Company.all.inject(Hash.new) do |hash, company|
      hash[company.request_host] = company.request_host
      hash
    end
end

#apartment.rb initializer
require 'apartment/elevators/host_hash'
Rails.application.config.middleware.use 'Apartment::Elevators::HostHash', Company.full_hosts_hash

API的用法:

// Service class that abstracts the server interface.
class Service
{
    // Return all StateA objects at the next server contact.
    public Task<IEnumerable<StateA>> GetStatesA() { ... }
    // Return all StateB objects at the next server contact.
    public Task<IEnumerable<StateB>> GetStatesB() { ... }
    // Send all queued requests to the server.
    public Task SendRequests() { ... }
}

据我所知,C#中的任务只能包装同步函数并在完成后返回。有没有办法从外面完成任务?

我正在寻找类似于Dart中的Completer类(参见https://api.dartlang.org/1.13.0/dart-async/Completer-class.html)。

2 个答案:

答案 0 :(得分:2)

您正在寻找的是ReadOuterXml()

public class Foo
{
    private readonly TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
    public Task GetStateA()
    {
        // Do stuff;
        return tcs.Task;
    }

    public Task GetStateB()
    {
        //Do stuff
        return tcs.Task;
    }

    public async Task QueryApiAsync()
    {
        // Query the API
        tcs.SetResult(true);
    }
}

虽然可以使用,但在我看来,您所曝光的API并不是非常方便。我不希望GetStateA()返回TaskIEnumerable<States>仅在批量查询执行后才会完成。我宁愿使用某种批处理方法,它提供Enqueue并在批处理完成后返回给调用者。如果您并未真正计划允许单个州查询API。

所以,我要么转变具有调用回调的public interface Foo { void Enqueue<T>(T state, Action callback) where T : State; } 方法的API方法:

public interface Foo
{
    Task<List<StateA>> GetStatesAAsync();
    Task<List<StateB>> GetStatesBAsync();
    Task<List<IState>> GetBatchStatesAsync(IEnumerable<IState> states);
}

或实际上公开了对API进行单一调用的功能,以及批处理操作:

{{1}}

答案 1 :(得分:0)

  

C#中的任务只能包装同步函数并在完成后返回。有没有办法从外面完成任务?

我想尝试回答这部分问题(同意@Yuval Itzchakov)。使用.NET 4.0在TPL中引入了TaskTask<T>类。最初,使用任务类的所需方法是使用流畅的API,即;链接ContinueWith。然而今天;最好将async / await关键字与Task返回方法一起使用。使用await将从外部“完成”任务,假设这就是你的意思。 await关键字将暂停方法的执行,直到等待的任务完成。