0

I have asp.net core controller that gets data from View and make search with it

Here is controller code

 private readonly GettingWords _repository;

    public HomeController(GettingWords repository){
        _repository = repository;
    }

    [HttpPost]
    public JsonResult SearchWord([FromBody] RequestModel model){
        var result = _repository.GettingWord(model.word, model.adress);
        return Json(result);
    }

Here is method that it calls

public class GettingWords
{
    public string  GettingWord(string word, string adress)
    {
        string result;
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(adress);
        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        Stream receiveStream = response.GetResponseStream();
        StreamReader readStream = null;

        if (response.CharacterSet == null)
        {
            readStream = new StreamReader(receiveStream);
        }
        else
        {
            readStream = new StreamReader(receiveStream, Encoding.GetEncoding(response.CharacterSet));
        }

        string data = readStream.ReadToEnd();
        string pattern = word;

        // Instantiate the regular expression object.
        Regex r = new Regex(pattern, RegexOptions.IgnoreCase);

        // Match the regular expression pattern against your html data.
        Match m = r.Match(data);

        if (m.Success)
        {
            result = "Word  " + word + "  finded in  " + adress;
        }
        else
        {
            result = "Word not finded";
        }
        response.Close();
        readStream.Close();
        return result;

    }
}

I need to run GettingWord in new Thread with those two parameters. How I can do this correctly?

UPDATE

Also I need to set max number of threads, so I think just Task<> is not great for this

Eugene Sukh
  • 2,357
  • 4
  • 42
  • 86
  • 2
    You should be using the `HttpClient` class with `GetAsync` and `GettingWord` should be declared as `public async Task GetWordAsync(string word, string adress)` – Camilo Terevinto Aug 15 '18 at 12:26
  • Okay. But also I need to declare max count of Threads, so maybe async Task is not suitable for this? @CamiloTerevinto – Eugene Sukh Aug 15 '18 at 12:28
  • 3
    No, you don't need to set the maximum number of threads at all. You think you need another thread, you don't. Use proper asynchronous patterns rather than attempting to force a threading model – Camilo Terevinto Aug 15 '18 at 12:30
  • I mean, in task is option - set max count of threads. @CamiloTerevinto – Eugene Sukh Aug 15 '18 at 12:31
  • 2
    What exactly do you think you will win with that? Creating threads just for the sake of creating them won't make your application faster – Camilo Terevinto Aug 15 '18 at 12:31
  • I think nothing , but it's just a task :( @CamiloTerevinto – Eugene Sukh Aug 15 '18 at 12:32
  • So I stuck with it, because I don't know how to do this @CamiloTerevinto – Eugene Sukh Aug 15 '18 at 12:32
  • 3
    Why do you need to run it in a new thread? What is the original thread going to be doing while waiting for your 'new thread' to complete? As @CamiloTerevinto point out, you should async and await. Task is perfect for this situation. Because waiting on a web request does not need a thread. Task will allow the thread to be used elsewhere until the web request returns. Using a proper async pattern will mean you create 0 extra threads so there is no need to worry about the max number of threads – Dave Aug 15 '18 at 12:39
  • @Dave it's just a test task. So I try to understood how to make it. – Eugene Sukh Aug 15 '18 at 12:40

3 Answers3

1

Your Getting Words class should look like this

public class GettingWords
{
    private static HttpClient _client = new HttpClient();

    public async Task<string>  GettingWordAsync(string word, string adress)
    {
        string result;
        string data = await _client.GetStringAsync(adress);
        string pattern = word;

        // Instantiate the regular expression object.
        Regex r = new Regex(pattern, RegexOptions.IgnoreCase);

        // Match the regular expression pattern against your html data.
        Match m = r.Match(data);

        if (m.Success)
        {
            result = "Word  " + word + "  finded in  " + adress;
        }
        else
        {
            result = "Word not finded";
        }
        return result;

    }
}

and be used like this

private readonly GettingWords _repository;

public HomeController(GettingWords repository){
    _repository = repository;
}

[HttpPost]
public async Task<JsonResult> SearchWord([FromBody] RequestModel model){
    var result = await _repository.GettingWordAsync(model.word, model.adress);
    return Json(result);
}
Dave
  • 2,829
  • 3
  • 17
  • 44
  • I have 400 Bad Request at this string `string data = await _client.GetStringAsync(adress);` – Eugene Sukh Aug 15 '18 at 12:53
  • that implies that the address you have in the adress variable is incorrect in someway use the debugger or write the console to get the value in that variable and try visiting through a web browser and see if it works – Dave Aug 15 '18 at 13:59
  • 1
    It works with google chrome. I rewrite code using HttpWebRequest – Eugene Sukh Aug 15 '18 at 14:11
1

I was able to solve async via this code

  public async Task<string> GettingWordAsync(string word, string adress)
    {
        HttpWebRequest req = WebRequest.CreateHttp(adress);
        req.Method = "GET";
        req.KeepAlive = true;   
        string result;
        string content = null;
        string pattern = word;
        HttpStatusCode code = HttpStatusCode.OK;
        try
        {
            using (HttpWebResponse response = (HttpWebResponse)await req.GetResponseAsync())
            {

                using (StreamReader sr = new StreamReader(response.GetResponseStream()))
                    content = await sr.ReadToEndAsync();

            }
        }
        catch (WebException ex)
        {

            using (HttpWebResponse response = (HttpWebResponse)ex.Response)
            {
                using (StreamReader sr = new StreamReader(response.GetResponseStream()))
                    content = sr.ReadToEnd();

                code = response.StatusCode;
            }

        }

                // Instantiate the regular expression object.
        Regex r = new Regex(pattern, RegexOptions.IgnoreCase);

        // Match the regular expression pattern against your html data.
        Match m = r.Match(content);

        if (m.Success)
        {
            result = "Word  " + word + "  finded in  " + adress;
        }
        else
        {
            result = "Word not finded";
        }
        return result;
    }
}
Eugene Sukh
  • 2,357
  • 4
  • 42
  • 86
  • If this work for you Eugene you can mark your own answer as the correct answer, makes it easier for future visitors to see what worked – Dave Aug 15 '18 at 14:23
  • I didn't know that there was a waiting time. You'll have to set yourself an alarm ;) – Dave Aug 15 '18 at 14:38
0

@Eugene the previous comment about the async Task was valid. If you need some more control over tasks count, you may set the max number in thread pool or anyhow change the default TaskScheduler (details could be found here for example). It is something that I would not recommend to do. it is very rear that someone really need that. Looks like in your case it might be incorrect/unclear business task. If you are sure that you really need to set max number of threads globally for that service, consider a building asynchronous pipeline with the TPL Dataflow

Artyom A.
  • 67
  • 4