Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
WCF-调用Web服务完成事件是在等待后执行_Wcf_Asynchronous_Async Await - Fatal编程技术网

WCF-调用Web服务完成事件是在等待后执行

WCF-调用Web服务完成事件是在等待后执行,wcf,asynchronous,async-await,Wcf,Asynchronous,Async Await,我调用了一个WCF,方法的完成事件是在等待方法之后调用的 public void my_method() { Task task = Task.Run(async () => await DoWorkAsync()); task.Wait(); } public async Task DoWorkAsync() { await Task.Run(() =>

我调用了一个WCF,方法的完成事件是在等待方法之后调用的

   public void my_method()
    {
        Task task = Task.Run(async () => await DoWorkAsync());       
        task.Wait();            
    }

    public async Task DoWorkAsync()
    {
        await Task.Run(() =>
         {
             wcf1.ServiceAnnonces s = new wcf1.ServiceAnnonces();
             s.DoWorkCompleted += S_DoWorkCompleted;
             s.DoWorkAsync();
         });
    }

    private string retour;
    public string Retour { get => retour; set => retour = value; }

    private void S_DoWorkCompleted(object sender, wcf1.DoWorkCompletedEventArgs e)
    { 
            Retour = e.Result;   
    }
我使用以下代码调用方法:

    Droid.Resources.ISvAnnoncesSoap s = new Droid.Resources.ISvAnnoncesSoap();
        s.ma_methode();

        LbResulat.Text = s.Retour;
我的服务:

 [ServiceContract]
    public interface IServiceAnnonces
    {
        [OperationContract]
        string DoWork();
    }

  public class ServiceAnnonces : IServiceAnnonces
    {

        public string DoWork()
        {
            return "coucou";
        }
    }
}
但在lbresult.Text=s.Retour之后抛出le Completed事件

谢谢你的帮助

编辑:

我删除了一些行代码。我现在的代码:

  public void ma_methode()
    {
        wcf1.ServiceAnnonces s = new wcf1.ServiceAnnonces();
        s.DoWorkCompleted += S_DoWorkCompleted;
        s.DoWorkAsync();         
    }

    private string retour;
    public string Retour { get => retour; set => retour = value; }

    private void S_DoWorkCompleted(object sender, wcf1.DoWorkCompletedEventArgs e)
    { 
            Retour = e.Result;   
    }
并直接致电:

 Droid.Resources.ISvAnnoncesSoap s = new Droid.Resources.ISvAnnoncesSoap();
            s.ma_methode();

        LbResulat.Text = s.Retour;
但相同,但完成的事件在lbresult.Text=s.Retour之后抛出;所以我的Retour是空的。

假设
DoWorkAsync()
DoWorkCompleted
是为您的WCF服务合约生成的客户端代理,那么“问题”是您没有阻止/等待
DoWorkCompleted
回调的完成-您正在调用
DoWorkAsync()
然后您的代码继续。稍后,WCF调用完成并调用回调(这就是WCF中异步客户端方法代理对的工作方式-它们早于.Net 4.5的
wait

您可以“重新同步”代码,例如,使用允许代码等待回调完成并发出任务已完成的信号:

public async Task DoWorkAsync()
{
     var tcsWorkDone = new TaskCompletionSource<bool>();
     wcf1.ServiceAnnonces s = new wcf1.ServiceAnnonces();
     s.DoWorkCompleted += (sender, e) =>
     {
        S_DoWorkCompleted(sender, e);
        tcsWorkDone.SetResult(true);
     };
     s.DoWorkAsync();
     await tcsWorkDone.Task;
 }
但是请注意,回调可以位于不同的线程上,因此您可能需要适当的(重新)调用代码来确保在UI线程上更新任何UI工件,如标签/文本框

Re:不使用任务。运行

比使用Task.Run更好的方法是

public async Task my_method()
{
    return await DoWorkAsync();
}
或者,如果没有其他工作,只需返回任务供调用者等待:

public Task my_method()
{
    return DoWorkAsync();
}
但是,如果您确实无法使my_方法异步,那么就不要使用
任务启动第二个线程。运行
然后在第一个线程上阻塞,然后您可以:


据猜测,
s.DoWorkAsync()
也是异步的,应该等待。我很确定您不需要所有这些
Task.Run的
——您能为
ServiceAnnonces.doworksync()提供代码或方法签名吗谢谢我编辑我的博文!非常感谢您的解释,我试着理解,并告诉您是否可以。我已经很久没有使用WCF了,但现在您似乎可以生成一个-这可能是处理代码的正确异步方式。
public Task my_method()
{
    return DoWorkAsync();
}
public void my_method()
{
    DoWorkAsync()
        .GetAwaiter()
        .GetResult();
}