使用异步回调方式解决等待耗时问题

在开发过程中,会遇到这样的场景:从客户端发起调用,这个调用的API耗时比较长,

通常解决方式是在服务端起一个线程去单独执行这块耗时的逻辑,主线程则直接返回结果。但是这样会遇到两个问题:
1.主线程中的数据传递问题

2.子线程处理完结果后,客户端怎么知道结果问题(如果客户端不需要结果则忽略)

 

解决第一个问题比较简单,主要是提醒一下别忘了传值。

而解决第二个问题则需要使用通知的方式,可以是RPC的通知,也可也使用SignalR做消息推送,也可以使用MQ通知,为了演示效果,我这边写了个demo使用的是RPC的方式

这种方式最简单

Client:

public class Client 
{
    private static ILogger<Client> _logger;
    public void DeleteFile() 
    {
        _logger = MyLogger.GetLogger<Client>();
        Service service = new Service();
        service.DeleteFile(CallBack);
    }

    public bool CallBack() 
    {
        _logger.LogInformation("RPC call the Client logics");
        return true;
    }
}

Service:

public class Service
{
    private static ILogger<Service> _logger;
    public void DeleteFile(Func<bool> callBack)
    {
        _logger = MyLogger.GetLogger<Service>();
        System.Threading.Tasks.Task.Run(() =>
        {
            for (int i = 0; i < 100; i++) 
            {
                _logger.LogInformation($"this is {i}");
            }

            callBack.Invoke();

            _logger.LogInformation("invoke callback done");
        });
    }

}  

为了演示效果集成了Nlog

Nlog.config

<?xml version="1.0" encoding="utf-8" ?>
<!-- XSD manual extracted from package NLog.Schema: https://www.nuget.org/packages/NLog.Schema-->
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
      internalLogFile="c:\temp\console-example-internal.log"
      internalLogLevel="Info" >

  <!-- the targets to write to -->
  <targets>
    <!-- write logs to file -->
    <target xsi:type="File" name="logfile" fileName="c:\temp\console-example.log"
            layout="${longdate}|${level}|${message} |${all-event-properties} ${exception:format=tostring}" />
    <target xsi:type="Console" name="logconsole"
            layout="${longdate}|${level}|${message} |${all-event-properties} ${exception:format=tostring}" />
  </targets>

  <!-- rules to map from logger name to target -->
  <rules>
    <logger name="*" minlevel="Trace" writeTo="logfile,logconsole" />
  </rules>
</nlog>

MyLogger:

public class MyLogger 
{
    public static ILogger<T> GetLogger<T>()
    {
        var logger = LoggerFactory.Create(builder => builder.AddNLog()).CreateLogger<T>();
        return logger;
    }
}

 

这个代码非常简单,主要是验证一下自己的想法,解决项目上的一个问题

  

 

posted @ 2025-02-18 10:29  DarryRing  阅读(47)  评论(0)    收藏  举报