C++双线程调用网络摄像头与多线程调用多摄像头同步执行方法详细讲解

目录
  • 一、使用双线程调用网络摄像头并执行算法
    • 方法一
    • 方法二
  • 二、使用多线程调用多路摄像头并同步执行多个算法

在调用网络摄像头处理自己的算法时,当解码的速度与算法运行的速度差太多时,会出现类似下面的错误

error while decoding MB 148 4, bytestream

所以需要使用两个线程,一个线程调用摄像头,一个线程用来处理图像。

一、使用双线程调用网络摄像头并执行算法

方法一

#include <iostream>
#include <thread>
#include <mutex>
#include <atomic>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
static std::mutex mutex;
static std::atomic_bool isOpen;
static void cameraThreadFunc(std::string camId, cv::Mat* pFrame)
{
    cv::VideoCapture capture(camId);
    //capture.set(cv::CAP_PROP_FOURCC, CV_FOURCC('M', 'J', 'P', 'G'));
    capture.set(cv::CAP_PROP_FPS, 30);
    if (!capture.isOpened()) {
        isOpen = false;
        std::cout << "Failed to open camera with index " << camId << std::endl;
    }
    cv::Mat frame;
    while (isOpen) {
        capture >> frame;
        if (mutex.try_lock()) {
            frame.copyTo(*pFrame);
            mutex.unlock();
        }
        cv::waitKey(5);
    }
    capture.release();
}
int main(int argc, char* argv[])
{
    std::string rtsps = "rtsp://admin:bs123456@192.168.1.64:554/h264/ch1/main/av_stream/1";
    isOpen = true;
    cv::Mat frame(1440, 2560, CV_8UC3);
    //cv::Mat* frame = new cv::Mat(1440, 2560, CV_8UC3);
    std::thread thread(cameraThreadFunc, rtsps, &frame); //调用摄像头
    //std::thread thread(cameraThreadFunc, rtsps, frame);
    //*****************************************************
    //调用自己的算法处理图像
    void* p_algorithm;
    p_algorithm = (void*)(new WindNetDetect());
    std::string net_bins = "./models/visdrone_1009-opt.bin";
    std::string net_paras = "./models/visdrone_1009-opt.param";
    int init_res = ((WindNetDetect*)p_algorithm)->init1(net_bins, net_paras);
    WindNetDetect* tmp = (WindNetDetect*)(p_algorithm);
    std::vector<Object> objects;
    //*****************************************************
    while (isOpen) {
        //*********************************
        //调用目标检测的算法
        tmp->detect(frame, objects);
        tmp->draw_objects(frame, objects);
        //*********************************
        if (cv::waitKey(1) == 'q') {
            break;
        }
    }
    frame.release();
    isOpen = false;
    thread.join();
    return 0;
}

方法二

// video_test.cpp
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <atomic>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
class VideoCaptureMT {
public:
	VideoCaptureMT(int index, int height=480, int width=640);
	VideoCaptureMT(std::string filePath, int height=480, int width=640);
	~VideoCaptureMT();
	bool isOpened() {
		return m_IsOpen;
	}
	void release() {
		m_IsOpen = false;
	}
	bool read(cv::Mat& frame);
private:
	void captureInit(int index, std::string filePath, int height, int width);
	void captureFrame();
	cv::VideoCapture* m_pCapture;
	cv::Mat* m_pFrame;
	std::mutex* m_pMutex;
	std::thread* m_pThread;
	std::atomic_bool m_IsOpen;
};
VideoCaptureMT::VideoCaptureMT(int index, int height, int width)
{
	captureInit(index, std::string(), height, width);
}
VideoCaptureMT::VideoCaptureMT(std::string filePath, int height, int width)
{
	captureInit(0, filePath, height, width);
}
VideoCaptureMT::~VideoCaptureMT()
{
	m_IsOpen = false;
	m_pThread->join();
	if (m_pCapture->isOpened()) {
		m_pCapture->release();
	}
	delete m_pThread;
	delete m_pMutex;
	delete m_pCapture;
	delete m_pFrame;
}
void VideoCaptureMT::captureInit(int index, std::string filePath, int height, int width)
{
	if (!filePath.empty()) {
		m_pCapture = new cv::VideoCapture(filePath);
	}
	else {
		m_pCapture = new cv::VideoCapture(index);
	}
	m_pCapture->set(cv::CAP_PROP_FRAME_WIDTH, width);
	m_pCapture->set(cv::CAP_PROP_FRAME_HEIGHT, height);
	m_pCapture->set(cv::CAP_PROP_FPS, 30);
	m_IsOpen = true;
	m_pFrame = new cv::Mat(height, width, CV_8UC3);
	m_pMutex = new std::mutex();
	m_pThread = new std::thread(&VideoCaptureMT::captureFrame, this);
}
void VideoCaptureMT::captureFrame()
{
	cv::Mat frameBuff;
	while (m_IsOpen) {
		(*m_pCapture) >> frameBuff;
		if (m_pMutex->try_lock()) {
			frameBuff.copyTo(*m_pFrame);
			m_pMutex->unlock();
		}
		cv::waitKey(5);
	}
}
bool VideoCaptureMT::read(cv::Mat& frame)
{
	if (m_pFrame->empty()) {
		m_IsOpen = false;
	}
	else {
		m_pMutex->lock();
		m_pFrame->copyTo(frame);
		m_pMutex->unlock();
	}
	return m_IsOpen;
}
int main(int argc, char* argv[])
{
	VideoCaptureMT capture(0);
	cv::Mat frame, gray;
	while (capture.isOpened()) {
		if (!capture.read(frame)) {
			break;
		}
		cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY);
		cv::blur(gray, gray, cv::Size(3, 3));
		cv::Canny(gray, gray, 5 , 38 , 3);
		cv::waitKey(100);
		cv::imshow("image", gray);
        if (cv::waitKey(5) == 'q') {
			break;
		}
	}
	capture.release();
	return 0;
}

二、使用多线程调用多路摄像头并同步执行多个算法

使用两个线程调用两个函数,get_cam1中包含了调用网络摄像头的类VideoCaptureMT (见上面代码),以及调用算法。另外一个函数是一样的。代码如下 :

void get_cam1()
{
	clock_t start, end, end1, end2;
	std::string rtsps = "rtsp://admin:bs123456@192.168.1.64:554/h264/ch1/main/av_stream/1";
	VideoCaptureMT capture(rtsps);
	//VideoCaptureMT capture, captureusb;
	cv::namedWindow("外接摄像头检测", 0);
	cv::Mat frame, gray;
	while (capture.isOpened()) {
		std::lock_guard<std::mutex> mtx_locker(mtx);
		start = clock();
		if (!capture.read(frame)) {
			break;
		}
		//gray = frame;
		end = clock();
		std::vector<Object> objects;
		tmp->detect(frame, objects);
		for (size_t i = 0; i < objects.size(); i++)
		{
			const Object& obj = objects[i];
			fprintf(stderr, "%d = %.5f at %.2f %.2f %.2f x %.2f\n", obj.label, obj.prob,
				obj.rect.x, obj.rect.y, obj.rect.width, obj.rect.height);
			cv::rectangle(frame, obj.rect, cv::Scalar(255, 0, 0));
			char text[256];
			//sprintf(text, "%s %.1f%%", class_names[obj.label], obj.prob * 100);
			sprintf(text, "%s", class_names[obj.label]);
			int baseLine = 0;
			cv::Size label_size = cv::getTextSize(text, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
			int x = obj.rect.x;
			int y = obj.rect.y - label_size.height - baseLine;
			if (y < 0)
				y = 0;
			if (x + label_size.width > frame.cols)
				x = frame.cols - label_size.width;
			cv::rectangle(frame, cv::Rect(cv::Point(x, y), cv::Size(label_size.width, label_size.height + baseLine)),
				cv::Scalar(255, 255, 255), -1);
			cv::putText(frame, text, cv::Point(x, y + label_size.height),
				cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0));
		}
		//cv::imwrite("./result20.jpg", image);
		cv::imshow("外接摄像头检测", frame);
		end2 = clock();
		float rumtime = (float)(end2 - start) / CLOCKS_PER_SEC;
		std::stringstream buf;
		buf.precision(3);//����Ĭ�Ͼ���
		buf.setf(std::ios::fixed);//����С��λ
		buf << rumtime;
		std::string strtime;
		strtime = buf.str();
		std::cout << "strtime1111 = " << strtime << std::endl;
		//start = end2;
		if (cv::waitKey(5) == 'q') {
			break;
		}
	}
	capture.release();
}
void get_camusb()
{
	clock_t start, end, end1, end2;
	std::string rtsps = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mp4";
	VideoCaptureMT capture(rtsps);
	cv::Mat frameusb;
	cv::namedWindow("外接摄像头检测1", 0);
	//void* p_algorithmusb;
	//p_algorithmusb = (void*)(new WindNetDetect());
	//std::string net_binsusb = "./models/visdrone_1009-opt.bin";
	//std::string net_parasusb = "./models/visdrone_1009-opt.param";
	//int init_res = ((WindNetDetect*)p_algorithmusb)->init1(net_binsusb, net_parasusb);
	//WindNetDetect* tmp = (WindNetDetect*)(p_algorithmusb);
	while (capture.isOpened()) {
		std::lock_guard<std::mutex> mtx_locker(mtx);
		start = clock();
		if (!capture.read(frameusb)) {
			break;
		}
		//gray = frame;
		end = clock();
		std::vector<Object> objectsusb;
		tmp->detect(frameusb, objectsusb);
		for (size_t i = 0; i < objectsusb.size(); i++)
		{
			const Object& obj = objectsusb[i];
			fprintf(stderr, "%d = %.5f at %.2f %.2f %.2f x %.2f\n", obj.label, obj.prob,
				obj.rect.x, obj.rect.y, obj.rect.width, obj.rect.height);
			cv::rectangle(frameusb, obj.rect, cv::Scalar(255, 0, 0));
			char text[256];
			//sprintf(text, "%s %.1f%%", class_names[obj.label], obj.prob * 100);
			sprintf(text, "%s", class_names[obj.label]);
			int baseLine = 0;
			cv::Size label_size = cv::getTextSize(text, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
			int x = obj.rect.x;
			int y = obj.rect.y - label_size.height - baseLine;
			if (y < 0)
				y = 0;
			if (x + label_size.width > frameusb.cols)
				x = frameusb.cols - label_size.width;
			cv::rectangle(frameusb, cv::Rect(cv::Point(x, y), cv::Size(label_size.width, label_size.height + baseLine)),
				cv::Scalar(255, 255, 255), -1);
			cv::putText(frameusb, text, cv::Point(x, y + label_size.height),
				cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0));
		}
		//cv::imwrite("./result20.jpg", image);
		cv::imshow("外接摄像头检测1", frameusb);
		end2 = clock();
		float rumtime = (float)(end2 - start) / CLOCKS_PER_SEC;
		std::stringstream buf;
		buf.precision(3);//����Ĭ�Ͼ���
		buf.setf(std::ios::fixed);//����С��λ
		buf << rumtime;
		std::string strtime;
		strtime = buf.str();
		std::cout << "strtime1111 = " << strtime << std::endl;
		//start = end2;
		if (cv::waitKey(5) == 'q') {
			break;
		}
	}
	capture.release();
}
int main() {
	void* p_algorithm;
	p_algorithm = (void*)(new WindNetDetect());
	std::string net_bins = "./models/visdrone_1009-opt.bin";
	std::string net_paras = "./models/visdrone_1009-opt.param";
	int init_res = ((WindNetDetect*)p_algorithm)->init1(net_bins, net_paras);
	tmp = (WindNetDetect*)(p_algorithm);
	//HANDLE hThread1 = CreateThread(NULL, 0, get_cam1, NULL, 0, NULL);
	//CloseHandle(hThread1);
	//HANDLE hThread2 = CreateThread(NULL, 0, get_camusb, NULL, 0, NULL);
	//CloseHandle(hThread2);
	std::thread thrd_1(get_cam1);
	std::thread thrd_2(get_camusb);
	thrd_1.join();
	thrd_2.join();
	while (true)
	{
		std::cout << "Main Thread Display!" << std::endl;
		Sleep(3000);
	}
	return 0;
}

运行上面的代码时,两个函数没有同步运行。如下strtime1111表示一个线程调用的函数,strtime2222表示另一个线程调用的函数,能看出没有同时调用两个函数。

所以需对代码进行如下改进:

static std::mutex mutexk;
void get_cam1()
{
	clock_t start, end, end1, end2;
	std::string rtsps = "rtsp://admin:bs123456@192.168.1.64:554/h264/ch1/main/av_stream/1";
	VideoCaptureMT capture(rtsps);
	cv::Mat frame;
	cv::namedWindow("ss", 0);
	while (capture.isOpened()) {
		//pthread_rwlock_rdlock(&rwlock);
		//std::lock_guard<std::mutex> mtx_locker(mtx);
		start = clock();
		if (!capture.read(frame)) {
			break;
		}
		if (mutexk.try_lock()) {
			//gray = frame;
			end = clock();
			std::vector<Object> objects;
			tmp->detect(frame, objects);
			//tmp->draw_objects(frame, objects);
			for (size_t i = 0; i < objects.size(); i++)
			{
				const Object& obj = objects[i];
				fprintf(stderr, "%d = %.5f at %.2f %.2f %.2f x %.2f\n", obj.label, obj.prob,
					obj.rect.x, obj.rect.y, obj.rect.width, obj.rect.height);
				cv::rectangle(frame, obj.rect, cv::Scalar(255, 0, 0));
				char text[256];
				//sprintf(text, "%s %.1f%%", class_names[obj.label], obj.prob * 100);
				sprintf(text, "%s", class_names[obj.label]);
				int baseLine = 0;
				cv::Size label_size = cv::getTextSize(text, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
				int x = obj.rect.x;
				int y = obj.rect.y - label_size.height - baseLine;
				if (y < 0)
					y = 0;
				if (x + label_size.width > frame.cols)
					x = frame.cols - label_size.width;
				cv::rectangle(frame, cv::Rect(cv::Point(x, y), cv::Size(label_size.width, label_size.height + baseLine)),
					cv::Scalar(255, 255, 255), -1);
				cv::putText(frame, text, cv::Point(x, y + label_size.height),
					cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0));
			}
			//cv::imwrite("./result20.jpg", image);
			cv::imshow("ss", frame);
			end2 = clock();
			float rumtime = (float)(end2 - start) / CLOCKS_PER_SEC;
			std::stringstream buf;
			buf.precision(3);//����Ĭ�Ͼ���
			buf.setf(std::ios::fixed);//����С��λ
			buf << rumtime;
			std::string strtime;
			strtime = buf.str();
			std::cout << "strtime2222 = " << strtime << std::endl;
			//start = end2;
			if (cv::waitKey(5) == 'q') {
				break;
			}
			mutexk.unlock();
		}
	}
	capture.release();
}
void get_camusb()
{
	//std::lock_guard<std::mutex> mtx_locker(mtx);
	clock_t start, end, end1, end2;
	//std::string rtsps = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mp4";
	std::string rtsps = "rtsp://admin:bs123456@192.168.1.64:554/h264/ch1/main/av_stream/1";
	VideoCaptureMT capture(rtsps);
	cv::Mat frameusb;
	cv::namedWindow("zz1", 0);
	while (capture.isOpened()) {
		std::lock_guard<std::mutex> mtx_locker1(mtx);
		start = clock();
		if (!capture.read(frameusb)) {
			break;
		}
		if (mutexk.try_lock()) {
			//gray = frame;
			end = clock();
			std::vector<Object> objectsusb;
			tmp->detect(frameusb, objectsusb);
			//tmp->draw_objects(frameusb, objectsusb);
			for (size_t i = 0; i < objectsusb.size(); i++)
			{
				const Object& obj = objectsusb[i];
				fprintf(stderr, "%d = %.5f at %.2f %.2f %.2f x %.2f\n", obj.label, obj.prob,
					obj.rect.x, obj.rect.y, obj.rect.width, obj.rect.height);
				cv::rectangle(frameusb, obj.rect, cv::Scalar(255, 0, 0));
				char text[256];
				//sprintf(text, "%s %.1f%%", class_names[obj.label], obj.prob * 100);
				sprintf(text, "%s", class_names[obj.label]);
				int baseLine = 0;
				cv::Size label_size = cv::getTextSize(text, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
				int x = obj.rect.x;
				int y = obj.rect.y - label_size.height - baseLine;
				if (y < 0)
					y = 0;
				if (x + label_size.width > frameusb.cols)
					x = frameusb.cols - label_size.width;
				cv::rectangle(frameusb, cv::Rect(cv::Point(x, y), cv::Size(label_size.width, label_size.height + baseLine)),
					cv::Scalar(255, 255, 255), -1);
				cv::putText(frameusb, text, cv::Point(x, y + label_size.height),
					cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0));
			}
			//cv::imwrite("./result20.jpg", image);
			cv::imshow("zz1", frameusb);
			end2 = clock();
			float rumtime = (float)(end2 - start) / CLOCKS_PER_SEC;
			std::stringstream buf;
			buf.precision(3);//����Ĭ�Ͼ���
			buf.setf(std::ios::fixed);//����С��λ
			buf << rumtime;
			std::string strtime;
			strtime = buf.str();
			std::cout << "strtime1111 = " << strtime << std::endl;
			//start = end2;
			if (cv::waitKey(5) == 'q') {
				break;
			}
			mutexk.unlock();
		}
	}
	capture.release();
}
int main() {
	void* p_algorithm;
	p_algorithm = (void*)(new WindNetDetect());
	std::string net_bins = "./models/visdrone_1009-opt.bin";
	std::string net_paras = "./models/visdrone_1009-opt.param";
	int init_res = ((WindNetDetect*)p_algorithm)->init1(net_bins, net_paras);
	tmp = (WindNetDetect*)(p_algorithm);
	std::thread thrd_1(get_cam1);
	std::thread thrd_2(get_camusb);
	thrd_1.join();
	thrd_2.join();
	while (true)
	{
		std::cout << "Main Thread Display!" << std::endl;
		Sleep(3000);
	}
	return 0;
}

使用多线线程调用多个函数同步执行模板如下:

#include <thread>
#include <mutex>
static std::mutex mutexk;
void func1() {
	while (capture1.isOpened()) {
		if (mutexk.try_lock()) {
			//我的算法
			my_func1();
            mutexk.unlock();
		}
	}
}
void func2() {
	while (capture2.isOpened()) {
		if (mutexk.try_lock()) {
			//我的算法
			my_func2();
            mutexk.unlock();
		}
	}
}
int main() {
	std::thread thrd_1(func1);
	std::thread thrd_2(func2);
	thrd_1.join();
	thrd_2.join();
	return 0;
}

在ubuntu中c++opencv多线程显示图片时出现Gdk-WARNING **: xx: Fatal IO error

解决办法:

1、sudo apt install libx11-dev

2、在代码中添加头文件#include <X11/Xlib.h>

3、在创建线程之前添加XInitThreads()

4、在编译的时候需要添加-lX11

参考链接:OpenCV视频流C++多线程处理方法详细分析

到此这篇关于C++双线程调用网络摄像头与多线程调用多摄像头同步执行方法详细讲解的文章就介绍到这了,更多相关C++调用网络摄像头内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++详解多线程中的线程同步与互斥量

    目录 线程同步 互斥量 线程同步 /* 使用多线程实现买票的案例. 有3个窗口,一共是100张票. */ #include <stdio.h> #include <pthread.h> #include <unistd.h> // 全局变量,所有的线程都共享这一份资源. int tickets = 100; void * sellticket(void * arg) { // 卖票 while(tickets > 0) { usleep(6000); //微秒 p

  • C++ 如何实现多线程与线程同步

    CreateThread 实现多线程: 先来创建一个简单的多线程实例,无参数传递版,运行实例会发现,主线程与子线程运行无规律. #include <windows.h> #include <iostream> using namespace std; DWORD WINAPI Func(LPVOID lpParamter) { for (int x = 0; x < 10; x++) { cout << "thread function" &l

  • C++同步线程实现示例详解

    目录 一.同步线程 二.独占访问示例 一.同步线程 虽然使用多线程可以提高应用程序的性能,但通常也会增加复杂性.如果同时执行多个函数,则必须同步对共享资源的访问.一旦应用程序达到一定大小,这将涉及大量的编程工作.本节介绍Boost.Thread提供的用于同步线程的类. 二.独占访问示例 示例 44.7.使用 boost::mutex 的独占访问 #include <boost/thread.hpp> #include <boost/chrono.hpp> #include <

  • C++双线程调用网络摄像头与多线程调用多摄像头同步执行方法详细讲解

    目录 一.使用双线程调用网络摄像头并执行算法 方法一 方法二 二.使用多线程调用多路摄像头并同步执行多个算法 在调用网络摄像头处理自己的算法时,当解码的速度与算法运行的速度差太多时,会出现类似下面的错误 error while decoding MB 148 4, bytestream 所以需要使用两个线程,一个线程调用摄像头,一个线程用来处理图像. 一.使用双线程调用网络摄像头并执行算法 方法一 #include <iostream> #include <thread> #inc

  • Java Feign微服务接口调用方法详细讲解

    目录 Feign说明 引入依赖启动类开启客户端 Feign接口开发 编写容错类 在业务层调用Feign客户端接口 Feign的常用属性如下 Feign说明 Feign是一种声明式.模板化的HTTP客户端.在spring cloud中使用Feign,可以做到类似于普通的接口的请求调用,可以发现对应的服务的接口,进而直接调用对应服务中的接口. 引入依赖启动类开启客户端 首先需要引入依赖 <dependency> <groupId>org.springframework.cloud<

  • Java多线程按指定顺序同步执行

    笔者今天看到一个有趣的面试题,如何让多个线程按照既定的顺序依次执行?比如每个线程输出一个整数, 那么期望就是这样的:0,1,2,3,4,5,6,7,8,9. 而不是0,2,4,1,3,5,8,7,9,6 乍一看,这不是反人性的考题吗?多线程本来就以乱序执行出名的.稍加思索,想到3种解决方案,分别用代码实现之. 方法1 使用newSingleThreadExecutor newSingleThreadExecutor返回仅仅包含一个线程的线程池,将多个任务交给此Executor时,这个线程池处理完

  • js调用网络摄像头的方法

    不支持IE浏览器(需要使用flash插件), 支持移动端, 未经过完全测试 PC端使用的时候, HTML页面需要预留video标签, canvas标签 移动端使用的时候, HTML页面需要预留file标签, canvas标签, img标签 (function (window, document) { window.camera = { init: function (options) { /** * options 属性示例 * videoID: video控件ID * canvasID: ca

  • js实现调用网络摄像头及常见错误处理

    最近由于业务的原因,需要在Web端页面接入调试各类的网络摄像头,遇到了很多匪夷所思的问题(说的就是读得出摄像头的品牌,读不出摄像头的分辨率).于是整理了这篇文章作为备忘录,也希望能帮到有类似的小伙伴们. 基础代码 navigator.mediaDevices.getUserMedia({ audio: false, video: true }).then(async (stream) => { let video = document.getElementById('#video') // 兼容

  • Python网络编程基于多线程实现多用户全双工聊天功能示例

    本文实例讲述了Python网络编程基于多线程实现多用户全双工聊天功能.分享给大家供大家参考,具体如下: 在前面一篇<Python网络编程使用select实现socket全双工异步通信功能>中,我们实现了1对1的异步通信,在文章结尾,给出了多对多通信的思路. 既然说了,咱就动手试一试,本次用的是多线程来实现,正好练练手- 首先讲一下思路: 我们将服务器做为中转站来处理信息,一方面与客户端互动,另一方面进行消息转发. 大体思路确定下来后,需要确定一些通信规则: 1. 客户端与服务器建立连接后,需要

  • 易语言实现双线程的方法解析

    易语言怎样写双线程? 一个线程循环找图.一个线程循环按键F2. .程序集变量 参数, 整数型 .程序集变量 线程句柄1, 整数型 .程序集变量 线程句柄2, 整数型 启动线程 (&子程序1, 参数,线程句柄1) 启动线程 (&子程序2, ,线程句柄2) .子程序 子程序1 .参数 参数1, 整数型 信息框 (参数1, 0, ) 信息框 ("这是线程1的例子", 0, ) .子程序 子程序2 信息框 ("这是线程2的例子", 0, ) 注意: 凡调用到

  • Linux多线程使用互斥量同步线程

    本文将会给出互斥量的详细解说,并用一个互斥量解决上一篇文章中,要使用两个信号量才能解决的只有子线程结束了对输入的处理和统计后,主线程才能继续执行的问题. 一.什么是互斥量 互斥量是另一种用于多线程中的同步访问方法,它允许程序锁住某个对象,使得每次只能有一个线程访问它.为了控制对关键代码的访问,必须在进入这段代码之前锁住一个互斥量,然后在完成操作之后解锁. 二.互斥量的函数的使用 它们的定义与使用信号量的函数非常相似,它们的定义如下: #include <pthread.h> int pthre

  • python多线程调用exit无法退出的解决方法

    python启用多线程后,调用exit出现无法退出的情况,原因是exit会抛出Systemexit的异常,如果在exit外围调用了try,就会出现ctrl+c两次才能退出的情况 解决方法: thread.setDaemon(True) thread.start() 线程启动前设置setDaemon(True) 以上这篇python多线程调用exit无法退出的解决方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • Java 使用多线程调用类的静态方法的示例

    1.情景展示 静态方法内部实现:将指定内容生成图片格式的二维码: 如何通过多线程实现? 2.分析 之所以采用多线程,是为了节省时间 3.解决方案 准备工作 logo文件 将生成的文件保存在F盘test目录下 代码实现 /**  * 多线程测试类  * @explain 生成图片格式的二维码采用多线程实现  * @author Marydon  * @creationTime 2018年11月23日下午3:15:39  * @version 1.0  * @since  * @email mary

随机推荐