首页 > 解决方案 > .NET Core 2.0 下面的代码线程安全吗

问题描述

这是我的代码,我对线程安全的实现有疑问。我的问题如下

  1. GetHtmlPageAsync 的返回值是对象。它是线程安全的吗?我将使用这个对象并添加到集合中,最后上传到数据库中。

  2. 主要方法逻辑如下(正在进行中)。我有一组域,我在集合中有 10000 个域的列表,我的想法是,我将其放入队列中并调用 GetHtmlPageAsync 以获取页面的 HTML。基于 HTML,我将获得必要的超链接。获得超链接后,我将检查链接中是否存在某些单词。如果该词在链接中可用,我将调用相同的方法 GetHTMLPageAsync 来获取该页面的 HTML。所以同一个线程可能会调用 GetHtmlPageAsync 来处理另一个链接。我正在尝试以线程安全的方式对多个调用重用相同的方法。请帮忙。

@edit1。我添加了主要方法。而不是队列。我用过 ForEach

public static async Task<int> ProcessDomainAsync(List<string> domains)
    {
        Parallel.ForEach(domains, async (currentDomain) =>
        {
            var domainBody = await GetHtmlPageAsync(currentDomain);
            var language = string.Empty;
            var country = string.Empty;
            var createdOn = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local);
            var updatedOn = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local);
            var machine = Environment.MachineName;
            var message = "[" + domainBody.ErrorCode + "] - " + domainBody.ErrorMessage;
            var active = false;
            var stage = "End";
            var url = currentDomain;
            if (domainBody.ErrorCode == 0)
            {
                var html = domainBody.Body;
                language = Common.GetLanguageIdentification(html);
                country = Common.GetCountryIdentification(currentDomain);
                message = string.Empty;
                active = true;
                stage = "Stage1";
                var hyperLinks = Common.GetAllAHrefTags(html);
                //Process Hyper Links
            }
            _domainList.Add(new Domain
            {
                Url = url,
                Language = language,
                Country = country,
                MachineName = machine,
                Message = message,
                Active = active,
                Stage = stage,
                CreatedOn = createdOn,
                UpdatedOn = updatedOn
            });
            domainCount++;
        });
        return domainCount;
    }
public class DomainBody
{
    public string Body;
    public string ErrorMessage;
    public int ErrorCode;
}

 public static class DomainProcessing    {

    static async Task<DomainBody> GetHtmlPageAsync(string url)
    {
        #region Initialize Proxy 
        var sessionId = new Random().Next().ToString();
        var proxy = new WebProxy(Constant.ProxyUrl, Constant.ProxyPort);
        var login = Constant.ProxyUserName + "-session-" + sessionId;
        proxy.Credentials = new NetworkCredential(login,Constant.ProxyPassword);
        #endregion

        #region Initialize Variables
        var user_agent = Common.GenerateRandomUserAgent();
        var body = string.Empty;
        var errorCode = 0;
        var errorMessage = string.Empty;
        #endregion

        try
        {
            #region Format URL with Http Protocol

            var domainSB = new StringBuilder();
            domainSB.Append("http://");
            domainSB.Append(url);

            #endregion

            #region Process Domain

            var request = (HttpWebRequest) WebRequest.Create(new Uri(url));
            request.Proxy = proxy;
            request.UserAgent = user_agent;
            request.Timeout = Constant.TimeOut;

            using (var response = await request.GetResponseAsync().ConfigureAwait(true))
            using (var content = new MemoryStream())
            using (var responseStream = response.GetResponseStream())
            {
                await responseStream.CopyToAsync(content);
                var bodyArray = content.ToArray();
                body = Encoding.UTF8.GetString(bodyArray, 0, bodyArray.Length);
            }

            errorCode = 0;
            errorMessage = string.Empty;

            #endregion 
        }
        catch (HttpRequestException ex)
        {
            body = string.Empty;
            errorCode = ex.InnerException.HResult;
            errorMessage = ex.InnerException.Message;
        }
        catch (Exception ex)
        {
            body = string.Empty;
            errorCode = ex.HResult;
            errorMessage = ex.Message;
        }

        var domainBody = new DomainBody
        {
            Body = body,
            ErrorCode = errorCode,
            ErrorMessage = errorMessage
        };

        return domainBody;
    }
}enter code here

标签: c#.netmultithreadingthread-safety

解决方案


一般来说,局部变量应该是线程安全的(只是因为他们不知道甚至还有另一个线程并且其他线程无法访问它们)。

应该查看可以被多个线程访问的任何内容。_domainList例如。确保该Add方法是线程安全的,因为您可能会并行调用它。


推荐阅读