0

I have a task that queries the local database and posts it to a web api. At the moment it takes all the rows, breaks them into chunks of 500 and then posts them all simultaneously using an async thread setup. I have another job that occasionally gets data from the server and I was thinking that if I returned the server load and stored it in Config.ServerLoad, it could space out the requests a bit if the server is getting hammered. Here is the code I use to setup my threads:

var json = JsonConvert.SerializeObject(rowDto);
var threads = new Thread(new ParameterizedThreadStart(MultiThreadPostThead));
var thisThread = new PostParams() { postUrl = postUrl, json = json, callingThread = threads };
threads.Start(thisThread);
threads.IsBackground = true;
ThreadHandles.Add(thisThread);

I was hoping to add something like this:

thread.delay(Config.ServerLoad * 1000);

If for instance the server load was 0.5, there would be almost no delay between threads, but if it was 10, it would wait 10 seconds between posts. I saw some info about a Task.Delay(), but didn't see anything for threads. Is there something I missed that would help add a dynamic value delay or set a max number of simultaneous threads?

Alan
  • 2,046
  • 2
  • 20
  • 43
  • If I understand right, you want to decrease load on your web api controllers. Current approach seems not appropriate here. Probably you should try something like https://github.com/stefanprodan/WebApiThrottle see https://stackoverflow.com/a/37774253/1606952 – chromigo Jun 12 '18 at 16:58
  • The load I want to decrease is on an Linux Apache server, thank you though for the nice package recommendation. – Alan Jun 12 '18 at 17:20

2 Answers2

1

If you're wanting to delay the starting of the new thread then you can do something along the line of

PerformanceCounter cpuCounter;
cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");

var thisThread = new PostParams() { postUrl = postUrl, json = json, callingThread = threads };
Thread.Sleep((int)(cpuCounter.NextValue() * 1000));
threads.Start(thisThread);

The other thing you could do is use

threads.Sleep((int)(cpuCounter.NextValue() * 1000));

as it is a Thread, so should have the method available

This should grab the current Cpu Usage and then sleep current thread for a certain time before starting the new thread - If you are already storing a number in the Config then you can just ditch the perform context stuff and replace it with the value you have :)

Gibbon
  • 2,633
  • 1
  • 13
  • 19
  • Thanks, the second option was what I ended up doing though I really like the first one if I was worried about the local cpu load. – Alan Jun 12 '18 at 17:21
0

I usually do not use threads myself, but prefer the Tasks as you mentioned.

.Net has a very straight forward async design pattern; by declaring your method async you define that the method is always supposed to be called in an asynchronous context. If you chose to use the following example, you will no longer have to wait a certain amount of time, but rather continue async execution upon finishing the task.

    public class MyResult {
        public string Result;
    }

    public async void Program() {

        var Timeout = 1000;
        Task<MyResult> Assignment = GetResult();

        // two ways of getting output:
        // 1: We wait using the task library
        Task.WaitAll(new Task[] { Assignment }, Timeout);
        MyResult r1 = Assignment.Result;

        // 2: We wait using the async methods:
        MyResult r2 = await Assignment;
    }

    public async Task<MyResult> GetResult() {
        // You can find methods which by default is async, therefore not needing to start the task yourself.
        return await Task.Factory.StartNew(() => LoadFromDatabase());
    }

    private MyResult LoadFromDatabase() {
        // Just testing.
        return new Question1.StartingTasks.MyResult() { Result = "TestResult" };
    }

If you are new to the async methods, I'd suggest to use some simple classes, like this example, to get to know the behaviour of these methods.

--- Extra

If you have used Task.Delay(Time) without success, you have to remember to wait for the Task to finish, e.g. Task.WaitAll(Task.Delay(500));