由于作者水平有限,如写得不对的地方望指正
当你的应用中有很耗时的操作需要执行时,我们一般采取异步的方式执行,先说一下我今天碰到的业务场景(我们是做医疗软件的):就是门诊医生站的病历,医生签署医嘱时,需要把医嘱信息插入到病历中并导出pdf并上传到文件服务器中(记为步骤1),医生撤销(取消签署)医嘱时,需要把病历中的医嘱信息去掉并导出pdf上传到文件服务器中(记为步骤2),但“导出pdf并上传到文件服务器”这一步很耗时,严重影响到用户的体验,首先想到的是用多线程的方式实现,但是这里有一个问题就是医生签署医嘱后马上撤销医嘱,这就有可能导致的问题是"步骤2"先于"步骤1"完成,最后保存到的pdf是错的。咨询过产品经理,需要保证最后拿到的那一份pdf是准确的(前面保存的容忍有一丢丢错误)。
试想一下,有没有一种方式,能把要执行的方法塞进队列中,然后循环拿出来执行呢,我想到的是反射+线程+安全队列实现,下面的方式,采用单独的线程来处理队列感觉不是很划算的,不知你有没有更好的方法。当然咯,下面的方法是备用方案,再想想有没有其它更优的方案,实在没有就采取该方案。
下面演示测试的Demo意思一下
1 新增控制台项目,并新增类MethodInfoInstance,如下:
public class MethodInfoInstance
{
public string MethodName { set; get; }
public string Param { set; get; }
}
2 新增类
public class TestMethod
{
public static ConcurrentQueue<MethodInfoInstance> infoQueue = new ConcurrentQueue<MethodInfoInstance>();
static TestMethod()
{
Thread thread = new Thread(StartInvokeMethodMethod);
thread.Start();
}
public void InvokeTestMethod(string number)
{
infoQueue.Enqueue(new MethodInfoInstance() { MethodName= "PrintOut", Param= number });
}
public void PrintOut(string param)
{
Console.WriteLine("输出:"+param);
}
private static void StartInvokeMethodMethod(object obj)
{
while (true)
{
if (infoQueue.Count > 0)
{
MethodInfoInstance methodInfoInstance =null;
infoQueue.TryDequeue(out methodInfoInstance);
if (methodInfoInstance != null)
{
Type type = typeof(TestMethod);
object instance = Activator.CreateInstance(type);
MethodInfo methodInfo = type.GetMethod(methodInfoInstance.MethodName);
methodInfo.Invoke(instance, new object[] { methodInfoInstance.Param });
Thread.Sleep(100);
}
}
else
{
Thread.Sleep(1000);
}
}
}
}
3 主程序代码如下:
class Program
{
static void Main(string[] args)
{
TestMethod testMethod = new TestMethod();
for (int i = 0; i < 10; i++)
{
testMethod.InvokeTestMethod(i.ToString());
}
Console.ReadLine();
}
}
最后运行结果为:
可以看到方法是顺序执行的