Although increase of hardware resources is the general trend in information technology, resource-constrained systems continue to be of relevance. In wireless sensor networks (WSN), for example, a typical device is equipped with a few kilobytes of RAM and provides only limited computing power. Such systems aim to provide ad-hoc and long- term monitoring of physical or environmental conditions over large spatial regions. Maximizing the number of participating devices and extending the overall network lifetime is crucial for such applications. Moore’s Law is therefore exploited towards lower device costs and lower power consumption at almost constant resource capabilities per device. This scarcity of resources has various implications on how resource-constrained systems such as wireless sensor networks are designed and implemented. Besides requiring highly optimized network protocols, one particularly important consequence is the prevalent adoption of the event-based programming paradigm. This paradigm is considered well-suited for traditional WSN applications, because it can be implemented efficiently and matches the reactive nature of such applications. However, requirements of WSN applications are continuously increasing, causing higher software complexity to meet growing expectations. As a result, today’s sensor networks often run IP stacks, HTTP and CoAP services, middleware, and other extensive software components. Implementing the complex control and data flows of such applications and services in an event-based manner is error-prone and the resulting code is hard to maintain. This leads to software faults that are costly and time consuming to track down, both during development and testing, and particularly during deployment and operation. Additionally, the presence of software faults entails security issues for a deployed system. To counter these problems, better programming abstractions for resource-constrained systems seem necessary. Threads are known for overcoming many problems of events by supporting sequential control flows via synchronous functions, but existing solutions either provide incomplete thread semantics or introduce a significant resource overhead. This reflects the common believe that expressiveness has to be traded for efficiency and vice versa. With our work, we show that this trade-off is not inherent to resource-constrained systems. We follow the approach of compiler-assisted thread abstractions, where full-fledged thread-based C code is compiled to equivalent event-based C code that runs atop an event-based operating system. This approach is promising for two reasons. First, the event-based run-time system avoids multiple preallocated stacks and the overhead of a task scheduler. And second, a compiler can, in contrast to a run-time-based thread library, perform static program analysis and thus apply application-specific optimizations. Our thesis is that a comprehensive thread abstraction is possible also for resource- constrained systems. A compiler, which translates thread-based applications into event- based programs, is able to combine the efficiency of event-based programming with the comfort of thread-based programming. This addresses the increasing requirements of resource-constrained systems. We develop our thesis in the context of wireless sensor networks, assuming that resource scarcity will continue to be relevant. Existing threading solutions either provide only limited thread semantics or require more resources than common WSN devices offer. We therefore propose a compiler-assisted approach that can provide a comprehensive and efficient thread abstraction. We support our thesis by presenting a comprehensive compiler-assisted thread abstraction concept for resource-constrained systems. To achieve this, we developed a platform-agnostic code transformation from thread-based C code to equivalent event- based C code. This enables developers to write thread-based applications without the additional costs of a thread library. Moreover, we present a way to reverse this transformation at run-time for fault diagnostics purposes. Hiding the details of the transformation and the underlying run-time system during all phases of development completes the abstraction. In order to evaluate our approach, we designed and implemented a compiler and a debugger prototype to conduct a set of experiments. Our results show that compiler-assisted thread abstractions not only outperform thread libraries, but are even almost as efficient as hand-written event-based code. The identified overhead accounts for only 1% higher RAM usage, 2% additional processor cycles, and 3% larger binaries on average, which we consider a reasonable trade-off for the gained comfort of a comprehensive thread abstraction. Additionally, the experiments demonstrate that sustaining the abstraction level for fault diagnostics is possible.