该方法主要针对的情况是:后台数据处理时间较长,前台请求在长时间未接收到后台的返回值时,会失去连接。因此可以使用ajax轮询定时向后台请求数据。
后台的多线程指的是将计算量比较大的部分放到子线程中进行处理,主线程依旧运行,并且返回结果(此结果不需要等待子线程跑完,只是先让前台得到响应)。
前台轮询部分:
var getting = { type: "Get", url: "xxx/xxx", data: {}, success: function (data: any) { if (data.length == 0) { //此处为后台返回值为空data表明子线程为跑完 setTimeout(function () { $.ajax(getting); }, 10000);//10秒后定时发送请求 } else { //这里是后台子线程跑完的处理 } } } $.ajax(getting);
后台多线程:
//主线程 [HttpPost("[action]")] public List<ResultFilters> ExonCompare(string sampleid,string gene,string enstId,int select_page=1,int tab_page=0) { //本地测试代码 List<string> inputSeq = new List<string>(); var path = @"d:\_txt"; using (var sr = new StreamReader(new FileStream(path, FileMode.Open))) { var line = sr.ReadLine(); var a = line.Split(" "); line = sr.ReadLine(); while (line != null && line != "") { var arr = line.Split(' '); inputSeq.Add(arr[7]); line = sr.ReadLine(); } } List<ThreadParam> paramList = new List<ThreadParam>(); ThreadParam threadParam = new ThreadParam(); threadParam.ListSeqPath = sampleid + "_" + gene + "_" + enstId + "_" + select_page + "_" + tab_page+"_"; threadParam.InputSeq = inputSeq[tab_page]; paramList.Add(threadParam); List<ResultFilters> rfs = new List<ResultFilters>(); ParameterizedThreadStart threadList = new ParameterizedThreadStart(OtherObject); Thread t = new Thread(threadList); t.Start(paramList); return rfs; }
public void OtherObject(object paramObj) { //paramObj在子线程中只能以object对象来传参,对象中可包含多个参数 List<ThreadParam> parm = (List<ThreadParam>)paramObj; var inputSeq = parm[0].InputSeq; var listSeqPath = parm[0].ListSeqPath; try { //耗时接口这里交给子线程 var list = _IExonsLibService.RNACompare_E(inputSeq, 0.98f).ToList(); List<ResultFilters> rfs = new List<ResultFilters>(); if (list.Count==0) { ResultFilters resultFilters = new ResultFilters(); resultFilters.FullNameParmPath = listSeqPath; resultFilters.ResultInfo = "未找到匹配序列"; rfs.Add(resultFilters); CallBackExonanalysis(rfs); // 通过委托, 将数据回传给回调函数 } List<ExonViewModel> result = new List<ExonViewModel>(); foreach (var item in list) { ExonViewModel info = new ExonViewModel(); info.ResultSeq = item.GetElement(1).ToString().Substring(6); info._id = ObjectId.Parse(item.GetElement(0).ToString().Substring(4)); var findseq = _IExonsLibService.FindSeq(info._id); var findinfo = _IExonsLibService.FindExonInfo(findseq.InfoId); info.FindSeq = findseq.Seq; info.Info_id = findinfo._id; info.StartExonPos = int.Parse(findinfo.StartCoordinate); info.EndExonPos = int.Parse(findinfo.EndCoordinate); info.GeneId = findinfo.GeneID; info.ExonId = findinfo.ExonID; info.InputSeq = inputSeq; int startComPos = info.ResultSeq.IndexOf("="); info.StartComPos = startComPos; int endComPos = info.ResultSeq.LastIndexOf("="); info.EndComPos = endComPos; //char[] usefulSeq = info.ResultSeq.Substring(startComPos, endComPos - startComPos + 1).ToCharArray(); info.EqualsCount = info.EndComPos - info.StartComPos + 1; result.Add(info); } var AN = result.OrderBy(p => p.StartComPos).ToList(); List<List<FilterViewModel>> unios = new List<List<FilterViewModel>>(); for (int i = 0; i < AN.Count;) { List<FilterViewModel> couple = new List<FilterViewModel>(); FilterViewModel filter = new FilterViewModel(); filter.Seq = AN[i].FindSeq; filter.StartExonPos = AN[i].StartExonPos; filter.EndExonPos = AN[i].EndExonPos; filter.GeneId = AN[i].GeneId; filter.ExonId = AN[i].ExonId; filter.EqualsCount = AN[i].EqualsCount; couple.Add(filter); int k = i; for (int j = i + 1; j < AN.Count; j++) { if (AN[k].EndComPos < AN[j].StartComPos) { FilterViewModel filter2 = new FilterViewModel(); filter2.Seq = AN[j].FindSeq; filter2.StartExonPos = AN[j].StartExonPos; filter2.EndExonPos = AN[j].EndExonPos; filter2.GeneId = AN[j].GeneId; filter2.ExonId = AN[j].ExonId; filter2.EqualsCount = AN[j].EqualsCount; couple.Add(filter2); k = k + 1; } } unios.Add(couple); i = i + 1; } List<CountWork> Ac = new List<CountWork>(); foreach (var items in unios) { CountWork n = new CountWork(); foreach (var m in items) { n.Allcount += m.EqualsCount; } Ac.Add(n); } //List<ResultFilters> rfs = new List<ResultFilters>(); if (Ac.Count != 0) { var max = Ac.Select(p => p.Allcount).Max(); var order = Ac.FindIndex(x => x.Allcount == max); var resultFilter = unios[order].OrderBy(p => p.StartExonPos).ToList(); var q = resultFilter.GroupBy(x => x.GeneId).ToList(); foreach (var n in q) { ResultFilters resultFilters = new ResultFilters(); resultFilters.GeneId = n.Key; var maxm = n.Select(p => p.EndExonPos).Max(); var minm = n.Select(x => x.StartExonPos).Min(); resultFilters.SeqLength = maxm - minm + 1; resultFilters.filterInfo = n.ToList(); resultFilters.FullNameParmPath = listSeqPath; rfs.Add(resultFilters); CallBackExonanalysis(rfs); // 通过委托, 将数据回传给回调函数 } } else { rfs.Add(null); CallBackExonanalysis(rfs); // 通过委托, 将数据回传给回调函数 } } catch { //List<ResultFilters> rfs = new List<ResultFilters>(); //CallBackExonanalysis(rfs); // 通过委托, 将数据回传给回调函数 } }
回调函数处理子线程的结果(此处是子线程的回调函数,处理结果可以写入txt文件):
public void CallBackExonanalysis(List<ResultFilters> rfs) { ... }
再通过txt文件转化为list,返回给前台
//读取文本文件转换为List [HttpGet("[action]")] public List<ResultFilters> ReadTextFileToList(string sampleid, string select_gene, string enstId, int select_page = 1, int tab_page = 0) { ... ... return list; }
最后前台可额外用一个单次请求首先请求这个ReadTextFileToList,如果list为空表明文件没有内容(也就是后台还未处理过数据)那么就调用主线程请求,否则不做任何处理。
//仅请求一次判断文件是否有结果 Axios.get('api/ExonCom/ReadTextFileToList', { params: { sampleid: query.sampleid, select_gene: query.select_gene, enstId: query.enstId, select_page: query.select_page, tab_page: _this.tab_page } }) .then(function (res: any) { if (res.data.length == 0) { //没结果 _this.ExonCompareFlag = true; if (_this.ExonCompareFlag == true) { _this.requestExonCompare(); } } else { _this.ExonCompareFlag = false; } }) .catch(function (error) { alert(error); });
requestExonCompare() { const _this = this; var query = _this.$route.query; let formData = new FormData(); let config = { headers: { 'Content-Type': 'multipart/form-data' } } formData.append("sampleid", query.sampleid); formData.append("gene", query.select_gene); formData.append("enstId", query.enstId); formData.append("select_page", query.select_page); formData.append("tab_page", _this.tab_page.toString()); Axios.post('api/ExonCom/ExonCompare', formData, config).then(function (res:any) { //console.log(res); }); }