Exemple #1
0
        // 独立 Task 版本
        // 首次检索
        public async Task <NormalResult> Search(
            UseCollection useList,
            IsbnSplitter isbnSplitter,
            string strQueryWord,
            int nMax,
            string strFromStyle,
            string strMatchStyle,
            delegate_searchCompleted searchCompleted,
            delegate_presentCompleted presentCompleted)
        {
            _searching = true;
            try
            {
                List <Task> tasks = new List <Task>();
                foreach (ZClientChannel channel in _channels)
                {
                    if (_searching == false)
                    {
                        break;
                    }

                    if (channel.Enabled == false)
                    {
                        continue;
                    }

                    var task = Task.Factory.StartNew <NormalResult>(
                        () =>
                    {
                        return(SearchOne(channel,
                                         useList,
                                         isbnSplitter,
                                         strQueryWord,
                                         nMax,
                                         strFromStyle,
                                         strMatchStyle,
                                         searchCompleted,
                                         presentCompleted));
                    });
                    tasks.Add(task);
                }

                await Task.Run(() =>
                {
                    Task.WaitAll(tasks.ToArray(), TimeSpan.FromMinutes(1));
                }).ConfigureAwait(false);

                return(new NormalResult());
            }
            finally
            {
                _searching = false;
            }
        }
Exemple #2
0
        // 针对一个特定 Z30.50 服务器发起检索
        async Task <NormalResult> SearchOne(
            ZClientChannel channel,
            UseCollection useList,
            IsbnSplitter isbnSplitter,
            string strQueryWord,
            int nMax,
            string strFromStyle,
            string strMatchStyle,
            delegate_searchCompleted searchCompleted,
            delegate_presentCompleted presentCompleted)
        {
            var ok = channel.Enter();

            try
            {
                if (ok == false)
                {
                    return(new NormalResult
                    {
                        Value = -1,
                        ErrorInfo = "通道已被占用",
                        ErrorCode = "channelInUse"
                    });
                }

                var             _targetInfo     = channel.TargetInfo;
                IsbnConvertInfo isbnconvertinfo = new IsbnConvertInfo
                {
                    IsbnSplitter = isbnSplitter,
                    ConvertStyle =
                        (_targetInfo.IsbnAddHyphen == true ? "addhyphen," : "")
                        + (_targetInfo.IsbnRemoveHyphen == true ? "removehyphen," : "")
                        + (_targetInfo.IsbnForce10 == true ? "force10," : "")
                        + (_targetInfo.IsbnForce13 == true ? "force13," : "")
                        + (_targetInfo.IsbnWild == true ? "wild," : "")
                        // TODO:
                        + (_targetInfo.IssnForce8 == true ? "issnforce8," : "")
                };

                string strQueryString = "";
                {
                    // 创建只包含一个检索词的简单 XML 检索式
                    // 注:这种 XML 检索式不是 Z39.50 函数库必需的。只是用它来方便构造 API 检索式的过程
                    string strQueryXml = BuildQueryXml(strQueryWord, strFromStyle);
                    // 将 XML 检索式变化为 API 检索式
                    var result = ZClient.ConvertQueryString(
                        useList,
                        strQueryXml,
                        isbnconvertinfo,
                        out strQueryString);
                    if (result.Value == -1)
                    {
                        searchCompleted?.Invoke(channel, new SearchResult(result));
                        var final_result = new NormalResult {
                            Value = result.Value, ErrorInfo = result.ErrorInfo
                        };
                        if (result.ErrorCode == "notFound")
                        {
                            final_result.ErrorCode = "useNotFound";
                        }
                        return(final_result);
                    }
                }

REDO_SEARCH:
                {
                    // return Value:
                    //      -1  出错
                    //      0   成功
                    //      1   调用前已经是初始化过的状态,本次没有进行初始化
                    // InitialResult result = _zclient.TryInitialize(_targetInfo).GetAwaiter().GetResult();
                    // InitialResult result = _zclient.TryInitialize(_targetInfo).Result;
                    InitialResult result = await channel.ZClient.TryInitialize(_targetInfo);

                    if (result.Value == -1)
                    {
                        searchCompleted?.Invoke(channel, new SearchResult(result));
                        // TODO: 是否继续向后检索其他 Z39.50 服务器?
                        return(new NormalResult {
                            Value = -1, ErrorInfo = "Initialize error: " + result.ErrorInfo
                        });
                    }
                }

                // result.Value:
                //		-1	error
                //		0	fail
                //		1	succeed
                // result.ResultCount:
                //      命中结果集内记录条数 (当 result.Value 为 1 时)
                SearchResult search_result = await channel.ZClient.Search(
                    strQueryString,
                    _targetInfo.DefaultQueryTermEncoding,
                    _targetInfo.DbNames,
                    _targetInfo.PreferredRecordSyntax,
                    "default");

                if (search_result.Value == -1 || search_result.Value == 0)
                {
                    if (search_result.ErrorCode == "ConnectionAborted")
                    {
                        // 自动重试检索
                        goto REDO_SEARCH;
                    }
                }

                searchCompleted?.Invoke(channel, search_result);
                channel._resultCount = search_result.ResultCount;

                if (search_result.Value == -1 ||
                    search_result.Value == 0 ||
                    search_result.ResultCount == 0)
                {
                    return(new NormalResult());  // continue
                }
                var present_result = await _fetchRecords(channel, PresentBatchSize /*10*/);

                presentCompleted?.Invoke(channel, present_result);

                if (present_result.Value != -1)
                {
                    channel._fetched += present_result.Records.Count;
                }

                return(new NormalResult());
            }
            finally
            {
                channel.Exit();
            }
        }
Exemple #3
0
        // 独立 Task 版本
        // 首次检索
        public async Task <NormalResult> SearchAsync(
            UseCollection useList,
            IsbnSplitter isbnSplitter,
            string strQueryWord,
            int nMax,
            string strFromStyle,
            string strMatchStyle,
            delegate_searchCompleted searchCompleted,
            delegate_presentCompleted presentCompleted)
        {
            _searching = true;
            try
            {
                List <Task <NormalResult> > tasks    = new List <Task <NormalResult> >();
                List <ZClientChannel>       channels = new List <ZClientChannel>();
                foreach (ZClientChannel channel in _channels)
                {
                    if (_searching == false)
                    {
                        break;
                    }

                    if (channel.Enabled == false)
                    {
                        continue;
                    }

                    var task = Task.Factory.StartNew(
                        async() =>
                    {
                        return(await SearchOne(channel,
                                               useList,
                                               isbnSplitter,
                                               strQueryWord,
                                               nMax,
                                               strFromStyle,
                                               strMatchStyle,
                                               searchCompleted,
                                               presentCompleted));
                    },
                        new CancellationToken(),
                        TaskCreationOptions.PreferFairness,
                        TaskScheduler.Default);

                    // tasks 和 channels 下标一一对应
                    tasks.Add(task.Unwrap());
                    channels.Add(channel);
                    Debug.Assert(tasks.Count == channels.Count);
                }

                /*
                 * await Task.Run(() =>
                 * {
                 *  Task.WaitAll(tasks.ToArray(), TimeSpan.FromMinutes(1));
                 * }).ConfigureAwait(false);
                 */
                await Task.WhenAny(Task.WhenAll(tasks), Task.Delay(TimeSpan.FromMinutes(1)));

                // 2020/11/4 观察返回值
                List <string> errors = new List <string>();
                foreach (var task in tasks)
                {
                    if (task.IsCompleted == false)
                    {
                        // 中断那些超时后还没有结束的 channel
                        int index   = tasks.IndexOf(task);
                        var channel = channels[index];
                        channel.ZClient.CloseConnection();
                        continue;   // 不计入报错?
                    }
                    var result = await task;
                    if (result.Value == -1)
                    {
                        errors.Add(result.ErrorInfo);
                    }
                }
                if (errors.Count == 0)
                {
                    return(new NormalResult());
                }
                else
                {
                    return new NormalResult
                           {
                               Value     = -1,
                               ErrorInfo = StringUtil.MakePathList(errors, "; ")
                           }
                };
            }
            finally
            {
                _searching = false;
            }
        }