Вот простая программа, запускающая 5 потоков, которые потребляют разное количество CPU, а затем сопоставляет то, что управляемый поток потребляет то, что количество CPU.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
class Program
{
[DllImport("Kernel32", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)]
public static extern Int32 GetCurrentWin32ThreadId();
static void Main(string[] args)
{
Dictionary<int, Thread> threads = new Dictionary<int, Thread>();
// Launch the threads
for (int i = 0; i < 5; i++)
{
Thread cpuThread = new Thread((start) =>
{
lock (threads)
{
threads.Add(GetCurrentWin32ThreadId(), Thread.CurrentThread);
}
ConsumeCPU(20 * (int)start);
});
cpuThread.Name = "T" + i;
cpuThread.Start(i);
}
// Every second wake up and see how much CPU each thread is using.
Thread monitoringThread = new Thread(() =>
{
Stopwatch watch = new Stopwatch();
watch.Start();
while (true)
{
Thread.Sleep(1000);
Console.Write("\r");
double totalTime = ((double)watch.ElapsedMilliseconds);
if (totalTime > 0)
{
Process p = Process.GetCurrentProcess();
foreach (ProcessThread pt in p.Threads)
{
Thread managedThread;
if (threads.TryGetValue(pt.Id, out managedThread))
{
double percent = (pt.TotalProcessorTime.TotalMilliseconds / totalTime);
Console.Write("{0}-{1:0.00} ", managedThread.Name, percent);
}
}
}
}
});
monitoringThread.Start();
}
// Helper function that generates a percentage of CPU usage
public static void ConsumeCPU(int percentage)
{
Stopwatch watch = new Stopwatch();
watch.Start();
while (true)
{
if (watch.ElapsedMilliseconds > percentage)
{
Thread.Sleep(100 - percentage);
watch.Reset();
watch.Start();
}
}
}
}
Обратите внимание, что возможно, что CLR изменит собственный поток, которым управляет поток. Однако на практике я не уверен, как часто это происходит.
Да. Существуют так называемые шаблонные правила . Самый простой для понимания пример:
%.o: %.cpp
$(CC) -c $(CFLAGS) $(CPPFLAGS) [110]lt; -o $@
(помните, что для Makefiles требуются вкладки ). Это правило описывает, как сделать объектный файл из файла cpp.
Если вам не нужно такое широкое правило, вы можете использовать так называемые статические шаблоны:
objects = file1.o file2.o file3.o
all: $(objects)
$(objects): %.o: %.cpp
$(CC) -c $(CFLAGS) $(CPPFLAGS) [111]lt; -o $@
Вот раздел о статических шаблонных правилах и шаблонных правилах в руководстве по GNU Make.
SRCS = a.c b.c
OBJS = $(SRCS:.c=.o)
.c.o:
${CC} ${CFLAGS} -c -o $@ [110]lt;
Хотя [111]lt;
не совсем переносимо (IIRC, bsdmake имеет значение $^
и [113]lt;
точно поменяно местами на то, что использует gmake), это рецепт по умолчанию для .c.o
, который будет действует в любой реализации.
Вы можете сделать это, как указано ниже:
SRCS=a.c b.c
OBJS=$(SRCS:.c=.o)
$(OBJS): $(SRCS)
cc -c -o a.o a.c
cc -c -o b.o b.c
, но вы должны помнить, что зависимости завершены - предполагается, что a.o
зависит от b.c
а также, что, вероятно, не так.
То, что вам, вероятно, нужно, это одно правило о том, как превратить один тип файла в другой:
SRCS=a.c b.c
OBJS=$(SRCS:.c=.o)
all: $(OBJS)
.c.o:
gcc -c -o $@ [111]lt;
.c.o
- это такое правило, которое указывает, какие команды нужно запустить, чтобы превратить .c
. ] файл в файл .o
. В фактической команде $@
заменяется конкретной целью, а [118]lt;
заменяется именем первой предпосылки.
Существует множество других автоматических переменных , которые вы можете использовать, найдите их в info make
или найдите хорошую книгу по make
, если у вас нет материала info
. 1118]